java.util.concurrent.BlockingQueue 是 Java 並發包中實現「生產者-消費者」模式的核心工具。本文深度解析五大經典實現類的特性、適用場景與代碼實戰。
| 隊列類型 | 底層結構 | 容量 | 順序策略 | 核心特性 | 典型場景 |
|---|---|---|---|---|---|
| ArrayBlockingQueue | 數組 | 有界 | FIFO | 公平鎖可選,效能穩定 | 固定緩衝區、任務調度 |
| LinkedBlockingQueue | 鏈表 | 可選有界 | FIFO | 吞吐量高,預設無界易 OOM | 高併發任務隊列、日誌緩衝 |
| DelayQueue | 堆 (PriorityQueue) | 無界 | 延遲時間排序 | 元素需實現 Delayed,到期才可取 | 定時任務、緩存過期清理 |
| PriorityBlockingQueue | 堆 | 無界 | 優先級排序 | 元素需 Comparable,不阻塞插入 | 優先級任務調度、醫療分診系統 |
| SynchronousQueue | 無緩衝 | 0 | 直接移交 | 插入必須等待取走,極高吞吐 | 線程池遷移任務、直接遞交場景 |
| 操作 | 拋出異常 | 返回布爾值 | 阻塞等待 | 超時等待 |
|---|---|---|---|---|
| 插入 | add(e) | offer(e) | put(e) | offer(e, time, unit) |
| 移除 | remove() | poll() | take() | poll(time, unit) |
| 檢查 | element() | peek() | 不可用 | 不可用 |
public class BlockingQueueDemo {
public static void main(String[] args) throws InterruptedException {
// 1. 有界隊列,生產快消費慢演示
BlockingQueue<String> queue = new ArrayBlockingQueue<>(5);
ExecutorService executor = Executors.newCachedThreadPool();
// 生產者:每 1 秒生產一個
executor.execute(() -> {
try {
for (int i = 0; i < 10; i++) {
String item = "item-" + i;
queue.put(item); // 隊列滿時阻塞
System.out.println("生產: " + item + " | 隊列大小: " + queue.size());
Thread.sleep(1000);
}
} catch (InterruptedException e) { Thread.currentThread().interrupt(); }
});
// 消費者:每 3 秒消費一個
executor.execute(() -> {
try {
while (true) {
String item = queue.take(); // 隊列空時阻塞
System.out.println("消費: " + item + " | 隊列大小: " + queue.size());
Thread.sleep(3000);
}
} catch (InterruptedException e) { Thread.currentThread().interrupt(); }
});
executor.shutdown();
}
}
class DelayTask implements Delayed {
private final long executeTime;
private final String taskName;
public DelayTask(String name, long delayMs) {
this.taskName = name;
this.executeTime = System.currentTimeMillis() + delayMs;
}
@Override public long getDelay(TimeUnit unit) {
return unit.convert(executeTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
@Override public int compareTo(Delayed o) {
return Long.compare(this.executeTime, ((DelayTask)o).executeTime);
}
}
// 使用
DelayQueue<DelayTask> delayQueue = new DelayQueue<>();
delayQueue.put(new DelayTask("發送郵件", 5000)); // 5 秒後執行
delayQueue.put(new DelayTask("清理緩存", 10000)); // 10 秒後執行
Executors.newCachedThreadPool() 內部使用 SynchronousQueue,新任務直接移交給空閒線程,無空閒線程則創建新線程,實現「零緩衝」高吞吐。