最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

徹底理解Java線程通信wait?/?notify(原理?+?實(shí)戰(zhàn))

 更新時(shí)間:2026年03月26日 09:53:48   作者:消失的舊時(shí)光-1943  
在Java中,wait和notify是Object類的一部分,用于線程間的通信和同步,它們允許一個(gè)線程通知另一個(gè)線程某個(gè)事件的發(fā)生,或者請求釋放對象的控制權(quán),這篇文章主要介紹了Java線程通信wait/notify的相關(guān)資料,需要的朋友可以參考下

前言

在 Java 多線程開發(fā)中,wait()、notify() 和 notifyAll() 是最經(jīng)典但也最容易寫錯(cuò)的一套線程通信機(jī)制。
它們用于解決:當(dāng)線程因?yàn)?ldquo;條件不滿足”無法繼續(xù)執(zhí)行時(shí),如何安全地等待并在條件改變后繼續(xù)執(zhí)行。

這篇文章將從原理、流程、示例到最佳實(shí)踐,把這三兄弟一次講透。

一、為什么需要 wait / notify?(最根本的問題)

在多線程場景中,經(jīng)常會(huì)出現(xiàn):

  • 消費(fèi)者想消費(fèi),但倉庫空了
  • 生產(chǎn)者想生產(chǎn),但倉庫滿了
  • 主線程需要等待子線程準(zhǔn)備好某個(gè)結(jié)果
  • 條件未滿足前,線程無法繼續(xù)往下執(zhí)行

如果用 while(true) 死循環(huán)檢查:

while (item == 0) {
    // 忙等(Busy waiting),瘋狂消耗 CPU
}

這會(huì)導(dǎo)致:

  • CPU 空轉(zhuǎn)
  • 性能極差
  • 線程爭搶激烈

于是,Java 提供了 基于鎖對象的條件等待機(jī)制

當(dāng)條件不滿足時(shí),線程主動(dòng)掛起自己,并釋放鎖;當(dāng)條件滿足時(shí),被其他線程喚醒繼續(xù)執(zhí)行。

這就是 wait / notify。

二、wait / notify 的正確理解(核心概念)

1. wait() 的本質(zhì)動(dòng)作

當(dāng)線程執(zhí)行:

lock.wait();

它會(huì)做 三件事

  1. 當(dāng)前線程暫停執(zhí)行(掛起)
  2. 釋放 lock 的那把鎖(讓其他線程有機(jī)會(huì)修改狀態(tài))
  3. 把自己加入 lock 對象的“等待隊(duì)列(Wait Set)”

線程會(huì)一直睡在那里,直到某個(gè)線程執(zhí)行了:

  • lock.notify() 或 lock.notifyAll()

并且:

  • ?? 喚醒的線程必須重新?lián)?lock 的鎖
  • 搶到鎖之后,才能繼續(xù)執(zhí)行 wait 后面的代碼

2. notify() / notifyAll() 做了什么?

兩個(gè)方法都必須在同步代碼塊中調(diào)用:

synchronized(lock) {
    lock.notify();
}

否則會(huì)拋:

IllegalMonitorStateException

notify() 作用:

  • 從 lock 的等待隊(duì)列中 隨機(jī)喚醒 1 個(gè)線程

  • 但喚醒 ≠ 立即執(zhí)行

  • 被喚醒線程要在當(dāng)前線程釋放鎖后才能搶鎖執(zhí)行

notifyAll() 作用:

  • 喚醒等待隊(duì)列中的所有線程

  • 所有線程一起去搶鎖,成功者繼續(xù)執(zhí)行

實(shí)際開發(fā)中一般推薦 notifyAll():更安全,避免喚醒錯(cuò)誤線程導(dǎo)致死鎖。

三、完整流程圖解(非常關(guān)鍵)

假設(shè)線程 A 想消費(fèi)商品,但倉庫空了:

線程 A 做的事:

  1. synchronized(lock) → 拿到鎖

  2. 判斷倉庫是否為空 → 是空的

  3. 調(diào)用 wait()

    • A 掛起

    • A 釋放鎖

    • A 進(jìn)入等待隊(duì)列

線程 B(生產(chǎn)者)做的事:

  1. synchronized(lock) → 拿到鎖

  2. 生產(chǎn)商品

  3. 調(diào)用 notify() 或 notifyAll():喚醒 A

  4. B 退出 synchronized → 釋放鎖

最后:

  • A 被喚醒

  • 搶到鎖后,繼續(xù)執(zhí)行 wait() 下一行的代碼

四、生產(chǎn)者消費(fèi)者完整 Demo(最經(jīng)典示例)

class Depot {
    private int item = 0;
    private final Object lock = new Object();
    public void produce() throws InterruptedException {
        synchronized (lock) {
            while (item == 1) {   // 倉庫滿 → 等待
                lock.wait();
            }
            item = 1;
            System.out.println("生產(chǎn)了一個(gè)商品");
            lock.notifyAll();     // 通知消費(fèi)者
        }
    }
    public void consume() throws InterruptedException {
        synchronized (lock) {
            while (item == 0) {   // 倉庫空 → 等待
                lock.wait();
            }
            item = 0;
            System.out.println("消費(fèi)了一個(gè)商品");
            lock.notifyAll();     // 通知生產(chǎn)者
        }
    }
}

為什么要用while而不是 if?

因?yàn)椋?/p>

  • Java 的 wait 存在 虛假喚醒(Spurious Wakeups)

  • 被喚醒后必須重新判斷條件

這是 JDK 官方文檔明確要求的。

五、wait 和 sleep 有什么區(qū)別?(面試必考)

特性waitsleep
屬于誰?ObjectThread
是否釋放鎖?釋放不釋放
是否必須在 synchronized 中?必須不需要
喚醒方式notify/notifyAll到點(diǎn)自動(dòng)醒

一句話總結(jié):

sleep 是讓線程睡覺
wait 是讓線程到等待隊(duì)列里等別人叫醒

六、常見錯(cuò)誤理解(90% 的人會(huì)踩坑)

1. 認(rèn)為 notify 會(huì)立即讓對方執(zhí)行

錯(cuò)誤!
notify 只是“叫醒”,對方必須等待 當(dāng)前線程釋放鎖 后才能執(zhí)行。

2. 不用 while,用 if 判斷條件

會(huì)導(dǎo)致喚醒后條件不滿足卻繼續(xù)執(zhí)行 → 出 Bug

3. 以為 wait 是“做完事情后休息”

完全相反!

wait 是因?yàn)樽霾幌氯ィ皇且驗(yàn)樽鐾炅恕?/strong>

4. wait 和 notify 不在同一個(gè)鎖對象上

比如:

a.wait();
b.notify();

永遠(yuǎn)喚不醒。

七、總結(jié)(建議背下來)

wait 的本質(zhì):

線程因?yàn)闂l件不滿足 → 掛起自己 → 釋放鎖 → 進(jìn)入等待隊(duì)列 → 等別人喚醒。

notify / notifyAll 的本質(zhì):

條件改變 → 喚醒等待隊(duì)列里的線程,讓它們重新?lián)屾i繼續(xù)執(zhí)行。

wait / notify 是同步代碼里的“條件等待機(jī)制”,不是休眠機(jī)制。

八、這套機(jī)制與 RxJava 背壓有什么關(guān)系?

其實(shí)本質(zhì)一樣:

  • RxJava 背壓:下游忙 → 上游暫停、等待或限速

  • wait/notify:條件不滿足 → 當(dāng)前線程暫停等待其他線程改變條件

都是:

生產(chǎn)速度與消費(fèi)速度不一致時(shí)的流量控制(Flow Control)思想。

總結(jié) 

到此這篇關(guān)于Java線程通信wait/notify的文章就介紹到這了,更多相關(guān)Java線程通信wait/notify內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

英德市| 体育| 敖汉旗| 辰溪县| 吉林省| 玉田县| 楚雄市| 安阳县| 体育| 西青区| 赞皇县| 安图县| 宝山区| 上饶市| 汾西县| 苏州市| 格尔木市| 霍城县| 珲春市| 阳朔县| 勐海县| 永仁县| 固始县| 隆昌县| 南康市| 涡阳县| 横峰县| 衢州市| 慈利县| 融水| 沂南县| 景洪市| 阿巴嘎旗| 平原县| 洞口县| 长春市| 庆元县| 江津市| 永泰县| 凭祥市| 犍为县|