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

Java中wait()和notify()的正確使用方式

 更新時(shí)間:2026年03月23日 09:54:09   作者:yingjuxia.com  
本文詳細(xì)介紹了Java中wait()和notify()方法的作用,包括讓線程阻塞并釋放鎖、喚醒等待線程等,通過實(shí)例演示了它們?cè)诙嗑€程同步中的應(yīng)用,,需要的朋友可以參考下

wait()、notify()、notifyAll()Object 類 的原生方法,是 Java 最早提供的線程間協(xié)作機(jī)制(屬于低級(jí)別、重量級(jí)的等待/通知機(jī)制)。

核心規(guī)則(必須全部記住,否則 100% 會(huì)出問題)

必須在 synchronized 塊/方法中調(diào)用

  • wait()、notify()、notifyAll() 都要求當(dāng)前線程持有同一個(gè)對(duì)象的監(jiān)視器鎖(monitor)
  • 否則拋出 IllegalMonitorStateException

wait() 會(huì)釋放鎖

  • 調(diào)用 wait() 后,當(dāng)前線程會(huì)釋放對(duì)象鎖,進(jìn)入該對(duì)象的等待隊(duì)列(wait set)

notify() / notifyAll() 不釋放鎖

  • 只是喚醒等待隊(duì)列中的一個(gè)/全部線程,但不立即把鎖給被喚醒的線程
  • 只有當(dāng)前持有鎖的線程離開 synchronized 塊后,被喚醒的線程才有機(jī)會(huì)競爭鎖

最經(jīng)典的寫法模板(生產(chǎn)級(jí)必須這樣寫)

// 消費(fèi)者
synchronized (lock) {
    while (conditionNotMet) {           // 必須用 while,不是 if?。ǚ乐固摷賳拘眩?
        lock.wait();                    // 釋放鎖并等待
    }
    // 條件滿足,消費(fèi)
    doConsume();
}

// 生產(chǎn)者
synchronized (lock) {
    // 生產(chǎn)
    doProduce();
    lock.notify();          // 或 notifyAll()
    // 離開 synchronized 塊后,被喚醒的線程才有機(jī)會(huì)搶鎖
}

為什么必須用 while 而不是 if?(虛假喚醒經(jīng)典坑)

虛假喚醒(spurious wakeup):線程可能在沒有被 notify 的情況下被系統(tǒng)喚醒(極少見,但 JVM 規(guī)范允許)。

// 錯(cuò)誤寫法(極易出問題)
if (queue.isEmpty()) {
    lock.wait();   // 被虛假喚醒后,可能直接往下執(zhí)行,而隊(duì)列還是空的
}

// 正確寫法(生產(chǎn)環(huán)境唯一推薦)
while (queue.isEmpty()) {
    lock.wait();
}

完整經(jīng)典示例:生產(chǎn)者-消費(fèi)者(固定大小隊(duì)列)

import java.util.LinkedList;
import java.util.Queue;

public class ProducerConsumer {

    private final Queue<Integer> queue = new LinkedList<>();
    private final int MAX_SIZE = 10;
    private final Object lock = new Object();

    class Producer implements Runnable {
        @Override
        public void run() {
            try {
                while (true) {
                    synchronized (lock) {
                        while (queue.size() == MAX_SIZE) {
                            System.out.println("隊(duì)列已滿,生產(chǎn)者等待...");
                            lock.wait();
                        }
                        int item = (int) (Math.random() * 100);
                        queue.offer(item);
                        System.out.println("生產(chǎn): " + item + ",當(dāng)前大小: " + queue.size());
                        lock.notifyAll();  // 喚醒所有等待的消費(fèi)者
                    }
                    Thread.sleep(500); // 模擬生產(chǎn)耗時(shí)
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }

    class Consumer implements Runnable {
        @Override
        public void run() {
            try {
                while (true) {
                    synchronized (lock) {
                        while (queue.isEmpty()) {
                            System.out.println("隊(duì)列為空,消費(fèi)者等待...");
                            lock.wait();
                        }
                        int item = queue.poll();
                        System.out.println("消費(fèi): " + item + ",當(dāng)前大小: " + queue.size());
                        lock.notifyAll();  // 喚醒可能等待的生產(chǎn)者
                    }
                    Thread.sleep(800); // 模擬消費(fèi)耗時(shí)
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }

    public static void main(String[] args) {
        ProducerConsumer pc = new ProducerConsumer();
        new Thread(pc.new Producer(), "生產(chǎn)者-1").start();
        new Thread(pc.new Consumer(), "消費(fèi)者-1").start();
        new Thread(pc.new Consumer(), "消費(fèi)者-2").start();
    }
}

常見錯(cuò)誤寫法匯總(你幾乎一定會(huì)踩)

錯(cuò)誤寫法后果正確做法
在 synchronized 外面調(diào)用 wait()IllegalMonitorStateException必須在 synchronized 內(nèi)
用 if 判斷條件而不是 while虛假喚醒導(dǎo)致邏輯錯(cuò)誤永遠(yuǎn)用 while
只用 notify() 而不用 notifyAll()可能導(dǎo)致部分線程永久等待(信號(hào)丟失)多消費(fèi)者/生產(chǎn)者場景用 notifyAll
notify() 后立即修改共享變量可能導(dǎo)致被喚醒線程看到舊狀態(tài)修改完再 notify
不同對(duì)象上 wait/notify線程永遠(yuǎn)喚不醒必須用同一個(gè)鎖對(duì)象

2025–2026 年真實(shí)項(xiàng)目中的選擇建議

場景推薦工具原因
簡單生產(chǎn)者-消費(fèi)者、線程間狀態(tài)等待wait/notify輕量、無額外依賴
需要超時(shí)等待Condition.await(long, TimeUnit)ReentrantLock 的 Condition 更靈活
大多數(shù)現(xiàn)代業(yè)務(wù)代碼BlockingQueue(ArrayBlockingQueue)封裝好了 wait/notify,API 更安全
高并發(fā)、復(fù)雜條件等待Condition + ReentrantLock支持多個(gè)等待隊(duì)列、公平鎖、可中斷
響應(yīng)式/異步場景CompletableFuture / reactor基本不再用原始 wait/notify

一句話總結(jié)(面試/生產(chǎn)最常問的答案):

“wait() 和 notify() 必須在同一個(gè)對(duì)象的 synchronized 塊中使用,wait() 會(huì)釋放鎖并進(jìn)入等待隊(duì)列,notify() 只喚醒但不釋放鎖,永遠(yuǎn)用 while 判斷條件,多線程協(xié)作場景優(yōu)先考慮 notifyAll()。”

以上就是Java中wait()和notify()的正確使用方式的詳細(xì)內(nèi)容,更多關(guān)于Java使用wait()和notify()的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java中LinkedList的模擬實(shí)現(xiàn)

    Java中LinkedList的模擬實(shí)現(xiàn)

    本文主要介紹了Java中LinkedList的模擬實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • Spring?Boot指定外部配置文件簡單示例

    Spring?Boot指定外部配置文件簡單示例

    Spring Boot可以讓你將配置外部化,這樣你就可以在不同的環(huán)境中使用相同的應(yīng)用程序代碼,這篇文章主要給大家介紹了關(guān)于Spring?Boot指定外部配置文件的相關(guān)資料,需要的朋友可以參考下
    2024-01-01
  • IntelliJ IDEA中加速M(fèi)aven編譯的終極指南

    IntelliJ IDEA中加速M(fèi)aven編譯的終極指南

    這篇文章主要為大家詳細(xì)介紹了IntelliJ IDEA中加速M(fèi)aven編譯的終極指南,從 7 分鐘提速到 30 秒,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下
    2025-10-10
  • Jmeter關(guān)聯(lián)實(shí)現(xiàn)及參數(shù)化使用解析

    Jmeter關(guān)聯(lián)實(shí)現(xiàn)及參數(shù)化使用解析

    這篇文章主要介紹了Jmeter關(guān)聯(lián)實(shí)現(xiàn)及參數(shù)化使用解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-08-08
  • Springboot整合Netty實(shí)現(xiàn)RPC服務(wù)器的示例代碼

    Springboot整合Netty實(shí)現(xiàn)RPC服務(wù)器的示例代碼

    這篇文章主要介紹了Springboot整合Netty實(shí)現(xiàn)RPC服務(wù)器的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • Python如何使用@property @x.setter及@x.deleter

    Python如何使用@property @x.setter及@x.deleter

    這篇文章主要介紹了Python如何使用@property @x.setter及@x.deleter,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-05-05
  • Java數(shù)學(xué)工具類MathUtil詳解

    Java數(shù)學(xué)工具類MathUtil詳解

    這篇文章主要為大家詳細(xì)介紹了Java數(shù)學(xué)工具類MathUtil的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-08-08
  • 深入淺析Java 抽象類和接口

    深入淺析Java 抽象類和接口

    這篇文章主要介紹了Java 抽象類和接口的相關(guān)知識(shí),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-11-11
  • Java 使用Socket正確讀取數(shù)據(jù)姿勢(shì)

    Java 使用Socket正確讀取數(shù)據(jù)姿勢(shì)

    這篇文章主要介紹了Java 使用Socket正確讀取數(shù)據(jù)姿勢(shì),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • javax.servlet不存在的解決辦法

    javax.servlet不存在的解決辦法

    今天在關(guān)于servlet的編譯中出現(xiàn)了一下小小的錯(cuò)誤,發(fā)現(xiàn)javax.servlet不存在,本文就介紹一下解決方法,感興趣的可以了解一下
    2021-07-07

最新評(píng)論

赞皇县| 滦平县| 万年县| 海阳市| 砚山县| 泗水县| 康平县| 沁源县| 玉林市| 新巴尔虎右旗| 恭城| 犍为县| 长丰县| 眉山市| 志丹县| 奈曼旗| 靖宇县| 泗水县| 昌邑市| 来安县| 长汀县| 寿宁县| 辽阳县| 陕西省| 双牌县| 新沂市| 泽州县| 隆林| 琼结县| 应城市| 垣曲县| 阿瓦提县| 哈尔滨市| 桃园县| 延安市| 汤阴县| 兰坪| 枣庄市| 灵石县| 增城市| 岗巴县|