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

Java 線程協作核心:wait/notify/notifyAll 機制詳解與實戰

     編輯:Java 綜合教學

三大核心方法

  • wait():當前線程釋放對象鎖,進入對象等待隊列,阻塞直至被喚醒或中斷。
  • notify():隨機喚醒對象等待隊列中**一個**線程(優先級高者機率大),喚醒後需重新獲取鎖才能繼續執行。
  • notifyAll():喚醒**所有**等待隊列線程,競爭鎖執行。

關鍵點: 調用前必須持有對象鎖(在 synchronized 塊內),否則拋 IllegalMonitorStateException。

狀態流轉圖解

wait/notify 狀態流轉

  1. 線程 A 持有鎖,調用 wait() → 釋放鎖,進入 Wait Set。
  2. 線程 B 獲取鎖,調用 notify() → 從 Wait Set 移出線程 A,進入 Entry Set 競爭鎖。
  3. 線程 B 釋放鎖(退出 synchronized) → 線程 A 獲取鎖 → 繼續執行 wait() 後代碼。

代碼演示:生產者-消費者模型

public class WaitNotifyDemo {
    private static final Object lock = new Object();
    private static boolean hasData = false;

    public static void main(String[] args) {
        new Thread(() -> {
            synchronized (lock) {
                System.out.println(Thread.currentThread().getName() + " 開始等待...");
                try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); }
                System.out.println(Thread.currentThread().getName() + " 被喚醒,繼續執行");
            }
        }, "Waiter").start();

        new Thread(() -> {
            synchronized (lock) {
                System.out.println(Thread.currentThread().getName() + " 發送通知");
                lock.notify();
                try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); }
                System.out.println(Thread.currentThread().getName() + " 釋放鎖");
            }
        }, "Notifier").start();
    }
}

輸出時間戳分析

1473306408730:Waiter 開始等待...
1473306408731:Notifier 發送通知
1473306418731:Waiter 被喚醒,繼續執行

Waiter 在 Notifier 調用 notify() 後**並未立即執行**,而是等待 Notifier 釋放鎖(睡眠 10 秒後),證明 notify 僅移出等待隊列,不釋放鎖。

最佳實踐

  1. 永遠在循環中調用 wait():while (!condition) lock.wait(); 防止虛假喚醒。
  2. 優先使用 notifyAll():除非確定只有一類等待條件,避免信號丟失導致線程永久阻塞。
  3. 鎖對象不可變:使用 final Object lock = new Object(); 專用鎖,避免業務對象鎖衝突。
  4. 高併發場景考慮 Condition:ReentrantLock.newCondition() 支持多條件隊列,精準喚醒,性能更優。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved