Queue是JDK 5以后引入的新的集合类,它属于Java Collections Framework的成员,在Collection集合中和List/Set是同一级别的接口。通常来讲Queue描述的是一种FIFO的队列,当然不全都是,比如PriorityQueue是按照优先级的顺序(或者说是自然顺序,借助于Comparator接口)。
下图描述了Java Collections Framework中Queue的整个家族体系。
对于Queue而言是在Collection的基础上增加了offer/remove/poll/element/peek方法,另外重新定义了add方法。对于这六个方法,有不同的定义。
抛出异常 |
返回特殊值 |
操作描述 |
|
插入 |
add(e) |
offer(e) |
将元素加入到队列尾部 |
移除 |
remove() |
poll() |
移除队列头部的元素 |
检查 |
element() |
peek() |
返回队列头部的元素而不移除此元素 |
特别说明的是对于Queue而言,规范并没有规定是线程安全的,为了解决这个问题,引入了可阻塞的队列BlockingQueue。对于BlockingQueue而言所有操作的是线程安全的,并且队列的操作可以被阻塞,直到满足某种条件。Queue的另一个子接口Deque描述的是一个双向的队列。与Queue不同的是,Deque允许在队列的头部增加元素和在队列的尾部删除元素。也就是说Deque是一个双向队列。二者功能都有的队列就是BlockingDeque,这种阻塞队列允许在队列的头和尾部分别操作元素,应该说是Queue中功能最强大的实现。
在JDK 5之前LinkedList就已经存在,而且本身实现都是一种双向队列。所以到了JDK 5以后就将LinkedList同时实现Deque接口,这样LinkedList就又属于Queue的一部分了。
通常情况下Queue都是靠链表结构实现的,但是链表意味着有一些而外的引用开销,如果是双向链表开销就更大了。所以为了节省内存,一种方式就是使用固定大小的数组来实现队列。在这种情况下队列的大小是固定,元素的遍历通过数组的索引进行,很显然这是一种双向链表的模型。ArrayDeque就是这样一种实现。
另外ArrayBlockingQueue也是一种数组实现的队列,但是却没有改造成双向,仅仅实现了BlockingQueue的模型。理论上和ArrayDeque一样也应该容易改造成双向的实现。
PriorityQueue和PriorityBlockingQueue实现了一种排序的队列模型。这很类似与SortedSet,通过队列的Comparator接口或者Comparable元素来排序元素。这种情况下元素在队列中的出入就不是按照FIFO的形式,而是根据比较后的自然顺序来进行。
CocurrentLinkedQueue是一种线程安全却非阻塞的FIFO队列,这种队列通常实现起来比较简单,但是却很有效。在接下来的章节会详细的描述它。
SynchronousQueue是一种特别的BlockingQueue,它只是把一个add/offer操作的元素直接移交给remove/take操作。也就是说它本身不会缓存任何元素,所以严格意义上说来讲并不是一种真正的队列。此队列维护一个线程列表,这些线程等待从队列中加入元素或者移除元素。简单的说,至少有一个remove/take操作时add/offer操作才能成功,同样至少有一个add/offer操作时remove/take操作才能成功。这是一种双向等待的队列模型,出队列等待加入等列,而入队列又等待出队列。这种队列的好处在于能够最大线程的保持吞吐量却又是线程安全的。所以对于一个需要快速处理的任务队列,SynchronousQueue是一个不错的选择。
BlockingQueue还有一种实现DelayQueue,这种实现允许每一个元素(Delayed)带有一个延时时间,当调用take/poll的时候会检测队列头元素这个时间是否<=0,如果满足就是说已经超时了,那么此元素就可以被移除了,否则就会等待。特别说明的是这个头元素应该是最先被超时的元素(这个时间是绝对时间)。这个类设计很巧妙,被用于ScheduledFutureTask来进行定时操作。希望后面会开辟一个章节讲讲这里面的想法。实在不行在讲线程池部分肯定会提到这个。
相关推荐
主要介绍了使用队列(Queue)解决简单的并发问题,讲解的很细致,喜欢的朋友们可以了解一下
一个快速多生产者,多消费者的C 11无锁并发队列
设计并发队列 代码如下:#include <pthread>#include <list>using namespace std; template <typename>class Queue { public: Queue( ) { pthread_mutex_init(&_lock, NULL); } ~Queue( ) { pthread_mutex_destroy(&...
fast-wait-free-queue, 并发队列实现的基准框架 快速等待空闲队列这是评估并发队列性能的基准测试框架。 目前,它包含4 个并发队列。 它们是:一个快速等待队列 wfqueueafek的Morrison和 lcrqkallimanis的Fatourou和...
concurrentqueue, 一种快速多消费者多消费者锁空闲并发队列 moodycamel::ConcurrentQueue面向 C 的工业强度锁自由队列。注意:如果你只需要一个生产者,单个消费者队列,我有其中的一个太多。特性Knock-your-socks-...
基于承诺的并发性受限的工作人员队列。 用法 // Create a queue with two worker threads const queue = new Queue ( 2 ) ; queue . onEmpty ( ( ) => { console . log ( 'done' ) ; } ) ; // Adding tasks to do ...
.Net Farmework中的普通队列Queue的实现使用了第一种方式,缺点是当队列空间不足会进行扩容,扩容的主要实现是开辟一个原始长度2倍的新数组,然后将原始数组里面的数据复制到新数组中,所以当扩容时就会产生不小的...
moodycamel :: ConcurrentQueue C ++的工业级无锁队列。 注意:如果您需要的只是一个单一生产者,单一消费者队列,那么我也可以选择。 特征 击倒你的。 单头实现。 只需将其放入您的项目中即可。 完全线程安全的...
基于python实现的sqlite队列,方便的处理sqlite并发。SqliteQueue是继承了threading.Thread的线程,并且维护了一个向sqlite请求的队列。支持peewee请求。SqlQuery简单的封装了SQL语句
p-queue:利用并发控制的Promise队列
Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue Algorithms
基于锁(Lock-Base)的算法实现扩充是相当容易的,但基于锁无关(Lock-Free)实现起来难度较大,下面将使用伪代码介绍基于Lock-Free实现可自适应扩充的环形并发队列算法,并提出了优化方案以使特定环境下能再提高...
具有优先级和因子的异步并发队列
p队列承诺队列并发控制对限制速率的异步(或同步)操作很有用。 例如,在与REST API交互时或在执行CPU /内存密集型任务时。安装$ npm install p-queue用法在这里,我们当时只兑现了一个承诺。 例如,将concurrency...
这是一个可以暂停的并发队列。 当其并发设置为1(默认)时,它是一个FIFO队列。 您可以将Promises放入此队列。 只能将X许诺作为您的配置并发执行。 您可以随时暂停/恢复此队列。 当队列暂停时,正在进行的承诺将...
使用工作池并具有可配置的并发 原料药 有关用法示例,请参见test.js var queue = require('atomic-queue')(worker, opts) 使用worker函数和可选选项初始化新队列。 queue是流 您可以通过将它们写入队列流来对它们...
什么是线程安全? 答:线程安全是多线程编程时的计算机程序代码中的一个概念。在拥有共享数据的多条线程并行执行的程序中,线程安全的...ConcurrentQueue<int> ts = new System.Collections.Concurrent.ConcurrentQueue
并发队列 并发多生产者多消费者队列。 有两种队列: 有限制的队列,容量有限。 无限队列无限制容量。 队列还可以随时关闭。 关闭后,尽管仍然可以弹出其余项目,但无法将更多项目推入队列。 这些功能使在此...