首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 生產者-消費者模式完整實現:wait/notify、阻塞隊列、虛假喚醒處理

     編輯:Java 相關知識

前言

生產者-消費者是多線程協作的經典模式:共享有界緩衝區,生產者放入、消費者取出。本文提供三個層次的實現:**基礎 wait/notify (教學用)、ArrayBlockingQueue (生產標準)、自定義條件變量 (進階控制)**,並深入解析 while 迴圈防虛假喚醒、鎖釋放時機、通知策略。

核心約束

  • 緩衝區大小固定 (有界),防止 OOM。
  • 生產者滿時阻塞,消費者空時阻塞。
  • 線程安全:互斥訪問 + 狀態協作。

實現一:基礎 wait/notify (教學演示)


關鍵點解析

關鍵點說明
synchronized 方法鎖住 Buffer 實例,保證互斥。
while (condition) wait()必須用 while:虛假喚醒、多線程競爭、notifyAll 喚醒非目標線程,醒來需重新檢查條件。
wait()釋放鎖,線程進入對象的 **Wait Set (等待集)**,不佔用 CPU。
notifyAll()將 Wait Set 中所有線程移至 **Entry Set (入口集/就緒隊列)** 競爭鎖。notify() 僅喚醒一個,若喚醒同類 (生產喚醒生產) 會導致活鎖,故用 notifyAll。

實現二:ArrayBlockingQueue (生產環境首選)

class AdvancedBuffer {
    private final int[] items = new int[10];
    private int putIdx = 0, takeIdx = 0, count = 0;
    private final ReentrantLock lock = new ReentrantLock();
    private final Condition notFull = lock.newCondition();
    private final Condition notEmpty = lock.newCondition();

    public void put(int x) throws InterruptedException {
        lock.lock();
        try {
            while (count == items.length) notFull.await(); // 精確等待「不滿」
            items[putIdx] = x;
            if (++putIdx == items.length) putIdx = 0;
            ++count;
            notEmpty.signal(); // 精確通知「不空」
        } finally { lock.unlock(); }
    }

    public int take() throws InterruptedException {
        lock.lock();
        try {
            while (count == 0) notEmpty.await();
            int x = items[takeIdx];
            if (++takeIdx == items.length) takeIdx = 0;
            --count;
            notFull.signal();
            return x;
        } finally { lock.unlock(); }
    }
}

優勢:可中斷鎖 (lockInterruptibly)、超時等待 (await(timeout))、多條件變量分離通知 (效能優於 notifyAll)、公平鎖選項。

進階主題

主題解決方案
優雅關閉引入 volatile boolean shutdown,生產者檢查退出,消費者 poll(timeout) 定期檢查。
背壓傳播生產者 offer(timeout) 失敗時觸發限流/丟棄/持久化策略 (Reactive Streams 規範)。
優先級消費PriorityBlockingQueue 或自定義 Condition 邏輯。
延遲消費DelayQueue (元素實作 Delayed)。
分佈式隊列Redis List (BLPOP)、RabbitMQ、Kafka、RocketMQ。

總結

生產者-消費者模式核心在於**有界緩衝區 + 互斥 + 狀態等待/通知**。教學階段理解 wait/notify 機制 (while 迴圈、鎖釋放、Wait Set/Entry Set) 是並發編程內功;**生產代碼直接使用 ArrayBlockingQueue 或 LinkedBlockingQueue**,專注業務邏輯。進階場景靈活運用 ReentrantLock + Condition、CompletableFuture、分佈式訊息隊列。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved