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

Java 多線程經典實戰:生產者-消費者模式完整演示

     編輯:Java 綜合教學

經典並發模式:生產者-消費者問題的 Java 實現

生產者-消費者模式是多線程編程中最基礎、最經典的協作模型。本文通過一個完整的示例,演示如何使用 wait()/notify()、synchronized 關鍵字實現線程間的數據同步與通信。

核心知識點回顧

  • Thread.start() vs run():啟動新線程 vs 普通方法調用
  • Thread.sleep():線程休眠,釋放 CPU 不釋放鎖
  • synchronized:內置鎖,保證原子性與可見性
  • wait()/notify():釋放鎖並進入等待隊列 / 喚醒等待線程,必須在 synchronized 塊中調用

類結構設計

三個核心類協作:

  • ObjectData:共享數據對象,封裝 count 變量及讀寫操作,內部使用 synchronized 保證線程安全。
  • ProductThread (生產者):循環遞增 count,寫入後 notify() 喚醒消費者,隨後 wait() 釋放鎖等待下一輪。
  • ConsumerThread (消費者):wait() 等待生產者通知,讀取 count 後 notify() 喚醒生產者。
類結構圖

完整代碼實現

共享數據對象

package com.gloomyfish.jse.thirdteen;

public class ObjectData {
    private int count = 0;

    public synchronized void read() {
        System.out.println("read count : " + count);
        System.out.println();
    }

    public synchronized void write() {
        count++;
        System.out.println("write count : " + count);
    }
}

消費者線程 (讀線程)

package com.gloomyfish.jse.thirdteen;

public class ConsumerThread extends Thread {
    private ObjectData data;

    public ConsumerThread(ObjectData data) {
        this.data = data;
    }

    @Override
    public void run() {
        while (true) {
            try {
                synchronized (data) {
                    data.wait();           // 釋放鎖,進入等待隊列
                    data.read();           // 讀取數據
                    data.notify();         // 喚醒生產者
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

生產者線程 (寫線程)

package com.gloomyfish.jse.thirdteen;

public class ProductThread extends Thread {
    private ObjectData data;

    public ProductThread(ObjectData data) {
        this.data = data;
    }

    @Override
    public void run() {
        while (true) {
            try {
                synchronized (data) {
                    data.write();              // 寫入數據 (count++)
                    Thread.sleep(3000);        // 模擬生產耗時
                    data.notify();             // 喚醒消費者
                    data.wait();               // 釋放鎖,等待消費者消費完畢
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

測試啟動類

public class MainTest {
    public static void main(String[] args) {
        ObjectData data = new ObjectData();           // 單一共享對象
        new ConsumerThread(data).start();             // 啟動消費者
        new ProductThread(data).start();              // 啟動生產者
    }
}

執行流程解析

  1. 主線程創建唯一 ObjectData 實例,分別傳給生產者和消費者。
  2. 生產者先獲取鎖,執行 write(),sleep(3s) 模擬耗時,調用 notify() 唤醒消費者,隨後 wait() 釋放鎖進入等待。
  3. 消費者被喚醒,獲取鎖,執行 read(),調用 notify() 唤醒生產者,循環回到 wait() 等待下一輪。
  4. 雙方通過 ObjectData 這把「鎖」實現嚴格的輪流執行:生產→消費→生產→消費…

關鍵注意點

  • wait/notify 必須配對使用:生產者 notify() 後必須 wait(),否則會連續生產導致邏輯錯誤。
  • 同步鎖對象必須一致:此處均使用 data 對象作為鎖,保證互斥。
  • while(true) 死循環:演示用;生產環境需引入關閉標誌位優雅停止。
  • spurious wakeup (虛假喚醒):生產環境建議用 while(condition) wait() 防禦。

總結

本例展示了 Java 基礎並發工具 (synchronized、wait/notify) 如何協作解決經典同步問題。實際開發中,更推薦使用 java.util.concurrent 包下的高級組件(如 BlockingQueue、Semaphore、Condition),代碼更簡潔、健壯且性能更優。

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