JavaSE 中的队列简介
一、Java 中的队列
Queue: 基本上,一个队列就是一个先入先出(FIFO)的数据结构。
Queue 接口与 List、Set同一级别,都是继承了Collection接口。
队列分为两大类:非阻塞队列和阻塞队列

二、非阻塞队列
非阻塞队列是指当队列已满时,插入操作立即返回失败,不会等待。当队列为空时,取出操作立即返回空值或抛出异常,不会等待。通常基于 CAS(Compare And Swap)等无锁算法实现,因此也叫“无锁队列”。
1. LinkedList(基于链表的FIFO队列)- 线程不安全
LinkedList 除了实现的 List 接口,也实现了 Deque 接口,可以当做双端队列来使用。
2. ArrayDeque(数组双端队列)- 线程不安全
ArrayDeque是Deque接口的一个实现,使用了可变数组,所以没有容量上的限制。同时,ArrayDeque是线程不安全的,在没有外部同步的情况下,不能在多线程环境下使用。
ArrayDeque是Deque的实现类,可以作为栈来使用,效率高于Stack;也可以作为队列来使用,效率高于LinkedList。需要注意的是,ArrayDeque不支持null值。
3. PriorityQueue(优先级队列)- 线程不安全
PriorityQueue 类实质上维护了一个有序列表。加入到 Queue 中的元素根据它们的天然排序(通过其 java.util.Comparable 实现)或者根据传递给构造函数的 java.util.Comparator 实现来定位。该队列不允许使用 null 元素也不允许插入不可比较的对象
PriorityQueue 队列的头指排序规则最小那个元素。如果多个元素都是最小值则随机选一个。
PriorityQueue 是一个无界队列,但是初始的容量(实际是一个Object[]),随着不断向优先级队列添加元素,其容量会自动扩容,无需指定容量增加策略的细节。
4. ConcurrentLinkedQueue(基于链表的并发队列)- 线程安全
ConcurrentLinkedQueue 是基于链接节点的、线程安全的队列(CAS)。并发访问不需要同步。因为它在队列的尾部添加元素并从头部删除它们,所以只要不需要知道队列的大小,ConcurrentLinkedQueue 对公共集合的共享访问就可以工作得很好。收集关于队列大小的信息会很慢,需要遍历队列。
同样此队列不允许使用null元素,
非阻塞队列的操作方法
- add(E e):将元素 e 插入到队列末尾,如果插入成功,则返回 true;如果插入失败(即队列已满),则会抛出异常;
- remove():移除队首元素,若移除成功,则返回 true;如果移除失败(队列为空),则会抛出异常;
- remove(Object o):移除指定的元素,若移除成功,则返回 true;如果移除失败(队列为空),则会抛出异常
- offer(E e):将元素 e 插入到队列末尾,如果插入成功,则返回 true;如果插入失败(即队列已满),则返回 false;
- poll():移除并获取队首元素,若成功,则返回队首元素;否则返回 null;
- peek():获取队首元素,若成功,则返回队首元素;否则返回 null
- isEmpty():队列是否为空
- size():队列长度
对于非阻塞队列,一般情况下建议使用 offer、poll 和 peek 三个方法,不建议使用 add 和 remove 方法。因为使用 offer、poll 和 peek 三个方法可以通过返回值判断操作成功与否,而使用 add 和 remove 方法却不能达到这样的效果。
注意:非阻塞队列中的方法都没有进行同步措施。
三、阻塞队列
阻塞队列是指当队列已满时,执行插入操作会阻塞,直到队列有空位。当队列为空时,执行取出操作会阻塞,直到队列有新元素。
注:生产者-消费者模型中最常用,天然支持“等待/通知”。
1. 阻塞队列
- ArrayBlockingQueue :一个由数组支持的有界队列。(基于数组的并发阻塞队列)- 线程安全
- LinkedBlockingQueue :一个由链接节点支持的可选有界队列。(基于链表的FIFO阻塞队列)- 线程安全
- PriorityBlockingQueue :一个由优先级堆支持的无界优先级队列。(带优先级的无界阻塞队列)
- DelayQueue :一个由优先级堆支持的、基于时间的调度队列。(延期阻塞队列)- 线程安全
- SynchronousQueue :一个利用 BlockingQueue 接口的简单聚集(rendezvous)机制。- 线程安全
- LinkedTransferQueue:一个由链表结构组成的无界阻塞队列。- 线程安全
- LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列。- 线程安全
2. 阻塞队列的操作方法
阻塞队列包括了非阻塞队列中的大部分方法,上面列举的5个方法在阻塞队列中都存在,但是要注意这5个方法在阻塞队列中都进行了同步措施。
除此之外,阻塞队列提供了另外4个非常有用的方法:
- put(E e):用来向队尾存入元素,如果队列满,则等待;
- take():用来从队首取元素,如果队列为空,则等待;
- offer(E e,long timeout, TimeUnit unit):用来向队尾存入元素,如果队列满,则等待一定的时间,当时间期限达到时,如果还没有插入成功,则返回false;否则返回true;
- poll(long timeout, TimeUnit unit):用来从队首取元素,如果队列空,则等待一定的时间,当时间期限达到时,如果取到,则返回null;否则返回取得的元素;
四、使用场景
| 场景 | 推荐 |
|---|---|
| 生产者-消费者解耦、线程池任务队列 | 阻塞队列 |
| 高并发、短任务、要求低延迟 | 非阻塞队列 |
| 允许任务丢弃或立即重试 | 非阻塞队列 |
总结一句话:阻塞队列用“等”来解决供需不匹配,非阻塞队列用“立即返回”来避免线程挂起。 选择时主要看业务能否接受阻塞等待,以及对性能和背压的要求。

浙公网安备 33010602011771号