java.util.concurrent 包提供了多種阻塞隊列,其中最核心的三種——SynchronousQueue、LinkedBlockingQueue、ArrayBlockingQueue——各有獨特的內存模型、鎖策略、適用場景。本文從源碼級原理剖析三者差異,給出生產環境選型建議。
| 特性 | SynchronousQueue | LinkedBlockingQueue | ArrayBlockingQueue |
|---|---|---|---|
| 底層數據結構 | 無數組/鏈表(直接傳遞) | 單向鏈表 | 環形數組 |
| 容量 | 0(邏輯上 1,但不存儲) | 無界(可選有界) | 有界(構造函數指定) |
| 鎖機制 | 公平/非公平鎖 + FIFO/LIFO 隊列 | 雙鎖(putLock/takeLock) | 單鎖(同一把 ReentrantLock) |
| 生產消費并行度 | 串行(必須一對一配對) | 高並行(雙鎖分離) | 串行(單鎖競爭) |
| 內存分配/GC | 無額外對象 | 每次入隊 new Node | 無額外對象(復用數組) |
| 典型場景 | 線程池直接提交、傳遞數據 | 高吞吐生產消費、日誌異步 | 固定緩存、內存敏感、低延遲 |
size() 永遠返回 0,peek() 永遠返回 null。Executors.newCachedThreadPool() 內部使用,任務直接移交給工作線程,無隊列積壓,線程空閒 60s 自動回收。Integer.MAX_VALUE,生產者極快、消費者極慢時極易 OOM!生產環境強制指定容量:`new LinkedBlockingQueue<>(10000)`。putLock 控制入隊,takeLock 控制出隊,生產與消費真正并行,吞吐極高。ReentrantLock 同步 put/take,生產消費串行,高并發下鎖競爭成為瓶頸。Doug Lea 認為操作輕量,引入雙鎖收益不抵復雜度。ArrayBlockingQueue(有界防 OOM),縮容線程池用 SynchronousQueue(無緩衝直接移交)。LinkedBlockingQueue(高吞吐、指定容量、異步消費)。ArrayBlockingQueue(零分配、確定性延遲)。queue.size() / capacity 使用率,設置告警閾值(如 80%)。三大隊列各有千秋:SynchronousQueue 傳遞、LinkedBlockingQueue 吞吐、ArrayBlockingQueue 確定性。理解底層鎖策略、內存模型、GC 行為,結合業務並發模式、內存預算、延遲要求,才能做出最優選型。切記:無界隊列生產環境禁用!