Java 中的 队列(Queue) 是一种遵循 FIFO(先进先出) 原则的数据结构,广泛用于任务调度、缓冲、线程间通信等场景。Java 集合框架提供了丰富的队列接口和实现类,它们的核心方法可以分为以下几类:
一、Queue 接口核心方法(共 6 个)
java.util.Queue 是所有队列的顶层接口,定义了 6 个核心操作方法,按“是否抛异常”分为两组:
| 方法 | 功能 | 成功时返回 | 失败时行为 |
|---|---|---|---|
add(e) | 插入元素 | true | 抛 IllegalStateException(队列满) |
offer(e) | 插入元素 | true | 返回 false(推荐使用) |
remove() | 删除并返回头部元素 | 队头元素 | 抛 NoSuchElementException |
poll() | 删除并返回头部元素 | 队头元素 | 返回 null(推荐使用) |
element() | 查看但不删除头部元素 | 队头元素 | 抛 NoSuchElementException |
peek() | 查看但不删除头部元素 | 队头元素 | 返回 null(推荐使用) |
最佳实践:优先使用带
o的方法(offer,poll,peek),避免异常,适合生产环境!
二、Deque 接口扩展方法(双端队列)
java.util.Deque(Double Ended Queue)是 Queue 的子接口,支持两端插入/删除,常用于栈、双向队列。
新增核心方法:
| 方法 | 作用 | 操作端 |
|---|---|---|
addFirst(e) / offerFirst(e) | 在队首插入 | 头部 |
addLast(e) / offerLast(e) | 在队尾插入 | 尾部 |
removeFirst() / pollFirst() | 删除并返回队首 | 头部 |
removeLast() / pollLast() | 删除并返回队尾 | 尾部 |
getFirst() / peekFirst() | 查看队首元素 | 头部 |
getLast() / peekLast() | 查看队尾元素 | 尾部 |
可以用
Deque实现:
- 栈:
push(e)=addFirst(e);pop()=removeFirst()- 双向队列:两端自由进出
三、常用实现类及其特性对比
| 实现类 | 是否线程安全 | 特点 | 适用场景 |
|---|---|---|---|
LinkedList | 否 | 双向链表实现,支持所有 Deque 方法 | 一般用途、非高并发 |
ArrayDeque | 否 | 数组实现,性能优于 LinkedList | 推荐作为普通队列/栈使用 |
PriorityQueue | 否 | 元素按自然顺序或 Comparator 排序 | 优先级任务调度 |
LinkedBlockingQueue | 是 | 阻塞队列,有界/无界 | 生产者-消费者模型 |
ArrayBlockingQueue | 是 | 有界阻塞队列,基于数组 | 高并发、固定容量 |
SynchronousQueue | 是 | 不存储元素,直接传递 | 线程间直接交接(如 ThreadPoolExecutor) |
DelayQueue | 是 | 延迟元素,只有到期才可取出 | 定时任务、缓存过期 |
PriorityBlockingQueue | 是 | 无界 + 优先级 | 需要排序的并发任务队列 |
四、阻塞队列(BlockingQueue)特有方法(重点!)
在多线程中,阻塞队列非常关键。它新增了阻塞式方法,当队列空或满时,会等待而不是立即失败。
| 方法 | 行为 |
|---|---|
put(e) | 插入元素,若队列满则阻塞等待 |
take() | 获取并移除元素,若队列空则阻塞等待 |
offer(e, timeout, unit) | 在指定时间内尝试插入,超时返回 false |
poll(timeout, unit) | 在指定时间内尝试获取,超时返回 null |
这些方法是 生产者-消费者模式 的基石!
示例:生产者-消费者模型
BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);
// 生产者
new Thread(() -> {
for (int i = 0; i < 5; i++) {
try {
queue.put("Task-" + i); // 阻塞直到有空间
} catch (InterruptedException e) { Thread.currentThread().interrupt(); }
}
}).start();
// 消费者
new Thread(() -> {
while (true) {
try {
String task = queue.take(); // 阻塞直到有数据
System.out.println("消费: " + task);
} catch (InterruptedException e) { break; }
}
}).start();
五、总结:Java 队列核心方法一览表(速查)
| 类型 | 方法 | 用途 | 推荐程度 |
|---|---|---|---|
| 基础队列 | offer(e) | 安全插入 | ⭐⭐⭐⭐⭐ |
poll() | 安全删除 | ⭐⭐⭐⭐⭐ | |
peek() | 安全查看 | ⭐⭐⭐⭐⭐ | |
add(e) | 危险插入(可能异常) | ⭐ | |
remove() | 危险删除(可能异常) | ⭐ | |
element() | 危险查看(可能异常) | ⭐ | |
| 双端队列 | offerFirst(e) / offerLast(e) | 两端插入 | ⭐⭐⭐⭐ |
pollFirst() / pollLast() | 两端删除 | ⭐⭐⭐⭐ | |
peekFirst() / peekLast() | 两端查看 | ⭐⭐⭐⭐ | |
| 阻塞队列 | put(e) | 阻塞插入 | ⭐⭐⭐⭐⭐ |
take() | 阻塞获取 | ⭐⭐⭐⭐⭐ | |
offer(e, timeout, unit) | 带超时插入 | ⭐⭐⭐⭐ | |
poll(timeout, unit) | 带超时获取 | ⭐⭐⭐⭐ |
六、面试高频考点
| 问题 | 答案要点 |
|---|---|
add() 和 offer() 区别? | add() 失败抛异常,offer() 返回 false,更安全 |
poll() 和 remove() 区别? | 同上,poll() 安全,remove() 可能抛异常 |
| 什么是阻塞队列? | 当队列空/满时自动阻塞线程,用于线程协作 |
| 哪些队列是线程安全的? | LinkedBlockingQueue, ArrayBlockingQueue, SynchronousQueue, PriorityBlockingQueue |
为什么推荐用 ArrayDeque 而不是 LinkedList? | 数组连续内存,缓存友好,性能更高 |
SynchronousQueue 是什么? | 不存储元素,每个插入必须等待另一个线程来取,用于线程直接交接 |
七、一句话总结
Java 队列的核心是:安全操作(offer/poll/peek)、阻塞能力(put/take)、以及根据场景选择合适的实现类——这是构建高性能并发系统的基础。
掌握这些方法,你就能轻松应对:
- 线程池任务调度
- 消息中间件设计
- 缓冲区管理
- 生产者-消费者模型

被折叠的 条评论
为什么被折叠?



