Java 集合框架中,Queue 及其子接口定義了「先進先出」「延遲調度」「阻塞協調」「雙端操作」「生產消費移交」等核心語義。本文系統梳理接口層次、方法契約、線程安全規範與典型應用模式,為選型與實現提供參考。

Collection
└─ Queue // 基礎隊列:offer/poll/peek + add/remove/element
├─ BlockingQueue // 阻塞隊列:put/take + 超時版
├─ Deque // 雙端隊列:首尾對稱操作
│ └─ BlockingDeque // 阻塞雙端隊列
└─ TransferQueue // 移交隊列:transfer() 生產者等待消費者
兩組等效方法(異常 vs 特殊值):
| 操作 | 拋出異常 | 返回特殊值 | 說明 |
|---|---|---|---|
| 入隊 | add(e) | offer(e) | 有界隊列滿時前者拋 IllegalStateException,後者返回 false |
| 出隊 | remove() | poll() | 隊列空時前者拋 NoSuchElementException,後者返回 null |
| 檢視隊首 | element() | peek() | 隊列空時行為同上 |
最佳實踐:生產代碼優先使用 offer/poll/peek,避免異常控制流;add/remove/element 適合測試/斷言場景。
| 類型 | 順序規則 | 典型實現 |
|---|---|---|
| FIFO | 先進先出 | LinkedList, ArrayDeque, LinkedBlockingQueue |
| LIFO | 後進先出(棧) | ArrayDeque (作棧用), ConcurrentLinkedDeque |
| 優先級 | 按 Comparator/自然序 | PriorityQueue, PriorityBlockingQueue |
共同點:remove()/poll() 始終返回「隊首」元素(FIFO 對應頭,LIFO 對應棧頂,優先級對應最高優先級)。
隊列中允許重複元素,且「順序」是核心屬性。基於內容的 equals 會導致兩個順序不同但元素相同的隊列被判定相等,違背語義。故繼承 Object 的身份相等。
四組操作形式:
| 操作 | 阻塞 | 超時 | 非阻塞 |
|---|---|---|---|
| 入隊 | put(e) | offer(e, timeout, unit) | offer(e) |
| 出隊 | take() | poll(timeout, unit) | poll() |
| 檢視 | — | — | peek() |
關鍵規範:
addAll 等除非文檔聲明否則不保證原子)null 元素:入隊 null 拋 NullPointerException,poll() 返回 null 表示空remainingCapacity(),無界返回 Integer.MAX_VALUE經典生產消費模式:
class Producer implements Runnable {
private final BlockingQueue- q;
public void run() { try { while (true) q.put(produce()); } catch (InterruptedException e) { ... } }
}
class Consumer implements Runnable {
private final BlockingQueue
- q;
public void run() { try { while (true) consume(q.take()); } catch (InterruptedException e) { ... } }
}
// 啟動多生產多消費
BlockingQueue
- q = new LinkedBlockingQueue<>();
new Thread(new Producer(q)).start();
new Thread(new Consumer(q)).start();
new Thread(new Consumer(q)).start();
不支持隨機訪問(無 get(index)),不建議存 null,繼承 Object 相等語義。
自有方法(首/尾對稱):
| 方向 | 拋出異常 | 特殊值 |
|---|---|---|
| 首部入隊 | addFirst(e) | offerFirst(e) |
| 尾部入隊 | addLast(e) | offerLast(e) |
| 首部出隊 | removeFirst() | pollFirst() |
| 尾部出隊 | removeLast() | pollLast() |
| 首部檢視 | getFirst() | peekFirst() |
| 尾部檢視 | getLast() | peekLast() |
| 首部移除指定 | removeFirstOccurrence(o) | |
| 尾部移除指定 | removeLastOccurrence(o) | |
作 FIFO 隊列等效映射:
| Queue 方法 | Deque 等效方法 |
|---|---|
add(e) | addLast(e) |
offer(e) | offerLast(e) |
remove() | removeFirst() |
poll() | pollFirst() |
element() | getFirst() |
peek() | peekFirst() |
作 LIFO 棧等效映射:
| Stack 方法 | Deque 等效方法 |
|---|---|
push(e) | addFirst(e) |
pop() | removeFirst() |
peek() | peekFirst() |
推薦:棧場景請用 ArrayDeque 替代舊 Stack 類(非線程安全、繼承 Vector、同步開銷大)。
組合 BlockingQueue 四組阻塞方法與 Deque 首尾對稱方法,共 20+ 方法。內存一致性同 BlockingQueue:入隊 happens-before 出隊。
典型實現:LinkedBlockingDeque(可選有界)。
核心方法:
transfer(E e):阻塞直到消費者調用 take()/poll() 移走元素(同步移交)tryTransfer(E e):非阻塞嘗試,有消費者等待則移交並返回 truetryTransfer(E e, timeout, unit):超時版hasWaitingConsumer():是否有消費者正在等待getWaitingConsumerCount():等待消費者數量典型實現:LinkedTransferQueue(無界、高性能、JDK 7+)。適用於「需要確認任務被接收」的場景,如線程池提交任務、RPC 請求等待處理。
| 場景 | 推薦實現 | 關鍵特性 |
|---|---|---|
| 單線程高性能 FIFO | ArrayDeque | 環狀數組、O(1) 兩端、無 GC 壓力 |
| 單線程棧 | ArrayDeque | 同上 |
| 多線程無界 FIFO | ConcurrentLinkedQueue | 無鎖 CAS、弱一致性、高吞吐 |
| 多線程有界 FIFO / 生產消費 | LinkedBlockingQueue | 雙鎖分離、阻塞協調、公平可選 |
| 多線程優先級隊列 | PriorityBlockingQueue | 堆有序、無界、阻塞 take |
| 多線程延遲/定時任務 | DelayedQueue | 基於 PriorityQueue、支持 Delayed 接口 |
| 多線程雙端操作 | ConcurrentLinkedDeque / LinkedBlockingDeque | 無鎖/阻塞雙端 |
| 生產者需確認消費者接手 | LinkedTransferQueue | transfer() 同步移交 |
| 線程間傳遞單個元素 | SynchronousQueue | 無容量、直接移交、ExecutorService 內部用 |
Queue 定義基礎語義,offer/poll/peek 為主力方法。BlockingQueue 增加阻塞協調,put/take 構建生產消費骨架,null 禁用。Deque 雙端對稱,ArrayDeque 同時替代 Stack 與 Queue。BlockingDeque = Blocking + Deque,LinkedBlockingDeque 唯一實現。TransferQueue 引入 transfer() 同步移交語義,LinkedTransferQueue 高性能實現。