Java Queue实现类包括LinkedList(双向链表)、PriorityQueue(堆排序)、ArrayDeque(循环数组高效)、LinkedBlockingQueue(线程安全阻塞)及ConcurrentLinkedQueue(CAS高并发),适用于生产者-消费者、任务调度和高频操作场景。
一、Queue 接口核心特性
-
先进先出(FIFO) :默认行为,但某些实现支持优先级或双端操作。
-
核心操作:
- 插入:
add(e)(失败抛异常)、offer(e)(失败返回false)。 - 移除:
remove()(失败抛异常)、poll()(失败返回null)。 - 检查:
element()(失败抛异常)、peek()(失败返回null)。
- 插入:
-
扩展功能:双端队列(
Deque)支持从两端插入和移除。
二、Queue 主要实现类对比
| 实现类 | 底层数据结构 | 线程安全 | 顺序特性 | 阻塞支持 | 适用场景 |
|---|---|---|---|---|---|
| LinkedList | 双向链表 | 非线程安全 | FIFO | 无 | 简单队列或双端队列操作 |
| PriorityQueue | 堆(数组) | 非线程安全 | 优先级排序 | 无 | 任务调度、按优先级处理 |
| ArrayDeque | 循环数组 | 非线程安全 | FIFO/LIFO | 无 | 高频插入删除、替代Stack |
| LinkedBlockingQueue | 链表 | 线程安全 | FIFO | 支持 | 生产者-消费者模型(无界或有界) |
| ArrayBlockingQueue | 数组 | 线程安全 | FIFO | 支持 | 固定容量阻塞队列 |
| ConcurrentLinkedQueue | 链表(CAS) | 线程安全 | FIFO | 无 | 高并发非阻塞队列 |
| PriorityBlockingQueue | 堆(数组) | 线程安全 | 优先级排序 | 支持 | 高并发优先级任务调度 |
三、各实现类详解
1. LinkedList(作为 Queue 使用)
-
底层数据结构:双向链表。
public class LinkedList<E> implements Deque<E> { transient Node<E> first; // 头节点 transient Node<E> last; // 尾节点 } -
操作复杂度:
- 插入/删除头尾元素:O(1)。
- 随机访问:O(n)。
-
适用场景:需要简单队列或双端队列,且无需线程安全。
2. PriorityQueue
-
底层数据结构:基于二叉堆的数组(最小堆或最大堆)。
// 堆结构示例(数组索引关系): parent(i) = (i-1)/2 leftChild(i) = 2*i + 1 rightChild(i) = 2*i + 2 -
排序规则:
- 自然排序:元素实现
Comparable接口。 - 定制排序:通过
Comparator指定。
- 自然排序:元素实现
-
扩容机制:
- 初始容量:默认 11。
- 扩容规则:容量小于64时翻倍,否则增加50%。
-
操作复杂度:插入(
offer)和删除(poll)均为 O(log n)。 -
适用场景:任务调度(如线程池)、事件优先级处理。
3. ArrayDeque
-
底层数据结构:循环数组(
Object[] elements)。public class ArrayDeque<E> implements Deque<E> { transient Object[] elements; transient int head; // 头指针 transient int tail; // 尾指针 } -
操作机制:
- 插入/删除头尾元素:O(1)。
- 自动处理数组循环(通过位运算
(head + 1) & (elements.length - 1))。
-
扩容机制:
- 初始容量:默认 16。
- 触发条件:
head == tail(数组已满)。 - 扩容规则:容量翻倍(保证始终是2的幂次)。
-
优点:内存紧凑,性能优于
LinkedList。 -
适用场景:高频队列/栈操作(如广度优先搜索)。
4. LinkedBlockingQueue
-
底层数据结构:单向链表(
Node节点)。static class Node<E> { E item; Node<E> next; } -
线程安全:通过
ReentrantLock和Condition实现。public class LinkedBlockingQueue<E> { private final ReentrantLock takeLock = new ReentrantLock(); private final Condition notEmpty = takeLock.newCondition(); private final ReentrantLock putLock = new ReentrantLock(); private final Condition notFull = putLock.newCondition(); } -
阻塞操作:
put(e):队列满时阻塞。take():队列空时阻塞。
-
容量控制:
- 默认无界(
Integer.MAX_VALUE),可指定固定容量。
- 默认无界(
-
适用场景:生产者-消费者模型(如线程池任务队列)。
5. ArrayBlockingQueue
-
底层数据结构:固定长度数组。
-
线程安全:全局
ReentrantLock+ 两个Condition(notEmpty和notFull)。 -
特点:
- 容量固定,初始化时指定。
- 公平性可选(通过构造函数指定
fair参数)。
-
性能:内存局部性好,但锁竞争较
LinkedBlockingQueue激烈。 -
适用场景:需要严格控制资源池大小的场景(如连接池)。
6. ConcurrentLinkedQueue
-
底层数据结构:基于单向链表的无锁队列(CAS 实现)。
public class ConcurrentLinkedQueue<E> { private transient volatile Node<E> head; private transient volatile Node<E> tail; } -
线程安全:通过
sun.misc.Unsafe的 CAS 操作(如compareAndSet)。 -
优点:高并发下性能优异(无锁)。
-
缺点:
size()方法复杂度为 O(n)。 -
适用场景:高并发非阻塞队列(如实时事件处理)。
7. PriorityBlockingQueue
- 底层数据结构:基于数组的堆(类似
PriorityQueue)。 - 线程安全:全局
ReentrantLock+Condition(notEmpty)。 - 扩容机制:容量不足时自动扩容(无界队列)。
- 适用场景:高并发优先级任务调度(如紧急事件处理)。
四、阻塞队列操作对比
| 方法 | 抛出异常 | 返回特殊值 | 阻塞 | 超时退出 |
|---|---|---|---|---|
| 插入 | add(e) | offer(e) | put(e) | offer(e, time, unit) |
| 移除 | remove() | poll() | take() | poll(time, unit) |
| 检查 | element() | peek() | - | - |
五、数据结构图示(Mermaid)
1. Queue 类图
«interface»Queue+offer()+poll()+peek()«interface»Deque+addFirst()+removeLast()«interface»BlockingQueue+put()+take()LinkedListPriorityQueueLinkedBlockingQueueArrayBlockingQueue
2. ArrayDeque 循环数组
ArrayDeque
5
head=2
tail=5
六、适用场景总结
-
单线程场景:
- 简单队列 →
ArrayDeque(性能最优)。 - 优先级处理 →
PriorityQueue。
- 简单队列 →
-
高并发场景:
- 非阻塞队列 →
ConcurrentLinkedQueue。 - 阻塞队列(生产者-消费者) →
LinkedBlockingQueue(无界)或ArrayBlockingQueue(固定容量)。 - 优先级阻塞队列 →
PriorityBlockingQueue。
- 非阻塞队列 →
-
双端操作需求 →
ArrayDeque或LinkedList。
七、示例代码:生产者-消费者模型
BlockingQueue<Task> queue = new LinkedBlockingQueue<>(10);
// 生产者
Runnable producer = () -> {
while (true) {
Task task = generateTask();
try {
queue.put(task); // 队列满时阻塞
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
};
// 消费者
Runnable consumer = () -> {
while (true) {
try {
Task task = queue.take(); // 队列空时阻塞
processTask(task);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
};
// 启动线程
new Thread(producer).start();
new Thread(consumer).start();
八、总结
-
Queue 核心价值:解耦生产者和消费者,平衡处理速度差异。
-
选择关键:
- 并发需求 → 选择线程安全实现。
- 顺序要求 → 普通队列 vs 优先级队列。
- 容量限制 → 无界队列 vs 有界队列。
-
性能优先:单线程用
ArrayDeque,高并发用ConcurrentLinkedQueue或LinkedBlockingQueue。