您的位置:首页 > 理论基础 > 数据结构算法

数据结构与算法:队列在有限资源池的应用

2020-06-03 05:41 323 查看
一、概念

先进先出,分为入队和出队。入队:放一个数据到队列尾部;出队:从队列头部取一个元素。

用数组实现的队列叫作顺序队列,用链表实现的队列叫作链式队列。

二、顺序队列

如图,abcd依次如对之后,队列中head指针指向下标为0的位置,tail指针指向下标为4的位置

当调用两次出队操作,队列中head指针指向下标为2的位置,tail指针仍指向下标为4的位置

随着数据入队和出队操作,head和tail都会持续往后移动。当tail移到最右边,即使数组中没有空闲空间,也无法继续往列表中添加数据了。所以要进行数据搬移(如果没有空闲空间,需要在入队时,集中触发一次数据的搬移操作)
当队列的 tail 指针移动到数组的最右边后,如果有新的数据入队,我们可以将 head 到 tail 之间的数据,整体搬移到数组中 0 到 tail-head 的位置。

三、链式队列

四、循环队列

数组实现队列时会有数据搬移操作,要想解决数据搬移问题,就需要循环队列

五、阻塞队列和并发队列

**阻塞队列:**在队列为空时,从队头取数据会被阻塞;如果队列已经满了,向队尾插入数据会被阻塞,直到队列中有空闲位置再插入。
**应用:**生产者消费者模式

生产者生产速度过快,消费者还来不及消费,存储数据的队列很快就会满了,这时候,生产者阻塞等待,直到消费者消费了数据,生产者才会唤醒继续生产。我们还可以通过多配置几个消费者来提高数据处理效率。
多线程同时操作队列,会出现线程安全问题,所以有线程安全的队列,并发队列

**并发队列:**线程安全的队列我们叫作并发队列。最简单直接的实现方式是直接在 enqueue()、dequeue() 方法上加锁,但是锁粒度大并发度会比较低,同一时刻仅允许一个存或者取操作。
实际上,基于数组的循环队列,利用 CAS 原子操作,可以实现非常高效的并发队列。这也是循环队列比链式队列应用更加广泛的原因。

六、线程池没有空闲线程时,新的任务请求线程资源时,线程池该如何处理?各种处理策略又是如何实现的呢?有界队列无界队列

一般有两种处理策略,一种是非阻塞的处理方式,直接拒绝任务请求;一种是阻塞的处理方式,将请求排队,等到空闲线程时,取出排队的请求继续处理。
基于链表的实现,可以实现一个支持无限排队的无界队列。但是可能会导致任务过多,响应时间过长,所以针对响应时间敏感的系统,基于链表实现的无限排队的线程池是不合适的。
基于数组的有界队列,队列大小有限,所以线程池中排队的请求超过队列大小时,接下来的请求就会被拒绝,对于响应敏感的系统合理。但是合理设置一个队列的大小也很讲究,队列太大导致等待请求太多,队列太小可能无法利用好系统资源。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: