java中队列接口是Queue。
它的子接口中包含两大类BlockingQueue阻塞队列和Deque双端队列,主要的继承结构如下:
一、Queue队列接口
1、PriorityQueue优先级队列
实现了Queue接口,不允许放入null
元素;其通过堆实现,具体说是通过完全二叉树实现的小顶堆
属于线程不安全队列,所以Java提供了PriorityBlockingQueue(实现BlockingQueue接口)用于java多线程环境
使用场景:主要用于排序输出(例如入队一些元素,出队时按从小到大或从大到小输出)
2、ConcurrentLinkedQueue并发链表队列
无锁结构
ConcurrentLinkedQueue是一个基于链接节点的无界线程安全队列,它采用先进先出的规则对节点进行排序,当我们添加一个元素的时候,它会添加到队列的尾部,当我们获取一个元素时,它会返回队列头部的元素。
ConcurrentLinkedQueue 是单向链表结构的无界并发队列。元素操作按照 FIFO (first-in-first-out 先入先出) 的顺序。适合“单生产,多消费”的场景。
使用场景:在并发的时候使用,多用于消息队列
二、Deque双端队列接口
1、ArrayDeque数组双端队列
是Deque接口的一个实现,使用了可变数组,所以没有容量上的限制。
同时,ArrayDeque是线程不安全的,在没有外部同步的情况下,不能再多线程环境下使用。
ArrayDeque是Deque的实现类,可以作为栈来使用,效率高于Stack;
也可以作为队列来使用,效率高于LinkedList。
需要注意的是,ArrayDeque不支持null值。
2、LinkedList
不用多说了吧。LinkedList既可以看作一个顺序容器,又可以看作一个队列(Queue),同时又可以看作一个stack栈
3、ConcurrentLinkedDeque并发链表双端队列
ConcurrentLinkedDeque 是双向链表结构的无界并发队列。与 ConcurrentLinkedQueue 的区别是该阻塞队列同时支持FIFO和FILO两种操作方式,即可以从队列的头和尾同时操作(插入/删除)。适合“多生产,多消费”的场景。
三、BlockingQueue阻塞队列
1、ArrayBlockingQueue数组阻塞队列
基于数组结构的有界阻塞队列,规定大小的BlockingQueue,其构造函数必须带一个int参数来指明其大小。其所含的对象是以FIFO(先入先出)顺序排序的
2、LinkedBlockingQueue链表阻塞队列
基于链表结构的阻塞队列,大小不定的BlockingQueue,若其构造函数带一个规定大小的参数,生成的BlockingQueue有大小限制,若不带大小参数,所生成的BlockingQueue的大小由Integer.MAX_VALUE来决定。其所含的对象是以FIFO顺序排序的,吞吐量通常要高于ArrayBlockingQueue
3、PriorityBlockingQueue优先级阻塞队列
具有优先级的无限阻塞队列,内部是堆结构,类似于LinkedBlockingQueue,但其所含对象的排序不是FIFO,而是依据对象的自然排序顺序或者是构造函数所带的Comparator决定的顺序
4、SynchronousQueue同步阻塞队列
不存储元素的阻塞队列,对其的操作必须是放和取交替完成的,每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQueue。
这种特性类似于Exchanger。和Exchanger不同的是,使用SynchronousQueue可以在两个线程中传递同一个对象。一个线程放对象,另外一个线程取对象。
5、DelayQueue延迟队列
支持延时的优先级的无界的阻塞队列,内部是堆结构
特点:
- DelayQueue是一个无界阻塞队列,队列内部使用PriorityQueue来实现。
- 进入队列的元素必须实现Delayed接口,在创建元素时可以指定多久才能从队列中获取当前元素,只有在延迟期满时才能从中提取元素;
- 该队列头部是延迟期满后保存时间最长的Delayed元素;
- 如果没有延迟未过期元素,且队列没有头部,并且poll将返回null;
- 当一个元素的getDelay(TimeUnit.NANOSECONDS)方法返回一个小于等于0的值时,表示该元素已过期;
- 无法使用poll或take移除未到期的元素,也不会将这些元素作为正常元素对待;例如:size方法返回到期和未到期元素的计数之和。
- 此队列不允许使用null元素。
使用应用场景:
- 缓存系统的设计:可以用DelayQueue保存缓存元素的有效期,使用一个线程循环查询DelayQueue,一旦能从DelayQueue中获取元素时,表示缓存有效期到了。
- 定时任务调度。使用DelayQueue保存当天将会执行的任务和执行时间,一旦从DelayQueue中获取到任务就开始执行,从比如TimerQueue就是使用DelayQueue实现的。
四、BlockingDeque阻塞双端队列
兼具阻塞和双端队列的特性的队列
1、LinkedBlockingDeque链表阻塞双端队列
五、TransferQueue传输队列
TransferQueue(java7引入)继承了BlockingQueue(BlockingQueue又继承了Queue)并扩展了一些新方法。生产者会一直阻塞直到所添加到队列的元素被某一个消费者所消费(不仅仅是添加到队列里就完事)。
1、LinkedTransferQueue链表传输队列(无锁结构)
该队列可以创建生产者和消费者程序并协调消息从生产者传输到消费者。
该实现类似于BlockingQueue类,但其可以实现反压形式传输,即当生产者利用transfer()方法发送消息给消费者时,生产者将一直被阻塞,直到消息被使用为止。