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

Java生產(chǎn)者和消費者實現(xiàn)等待喚醒機制

 更新時間:2025年06月05日 09:54:21   作者:寶耶  
本文主要介紹了Java生產(chǎn)者和消費者實現(xiàn)等待喚醒機制,通過synchronized、wait()和notifyAll()實現(xiàn)線程間的安全協(xié)作,具有一定的參考價值,感興趣的可以了解一下

本文將介紹如何使用Java多線程實現(xiàn)經(jīng)典的生產(chǎn)者-消費者模型,通過synchronized、wait()和notifyAll()實現(xiàn)線程間的安全協(xié)作。

模型概述

生產(chǎn)者-消費者模型是多線程編程中的經(jīng)典案例,主要解決以下問題:

  • 生產(chǎn)者線程負責生產(chǎn)數(shù)據(jù)/資源
  • 消費者線程負責消費數(shù)據(jù)/資源
  • 生產(chǎn)者和消費者通過共享緩沖區(qū)進行通信
  • 需要解決線程同步和資源競爭問題

完整代碼實現(xiàn)

1. Desk.java(共享數(shù)據(jù)類)

/**
 * 共享數(shù)據(jù)類
 * - foodflag: 食物狀態(tài)標記(0=無食物,1=有食物)
 * - count: 剩余食物數(shù)量
 * - lock: 同步鎖對象
 */
public class Desk {
    public static int foodflag = 0;
    public static int count = 10;
    public static final Object lock = new Object();
}

2. Cook.java(生產(chǎn)者線程)

/**
 * 生產(chǎn)者線程 - 廚師
 */
public class Cook extends Thread {
    @Override
    public void run() {
        while (true) {
            synchronized (Desk.lock) {
                // 如果食物已全部生產(chǎn)完成,則退出
                if (Desk.count == 0) {
                    break;
                }
                
                // 如果還有食物未被消費,則等待
                if (Desk.foodflag == 1) {
                    try {
                        Desk.lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    // 生產(chǎn)食物
                    System.out.println(Thread.currentThread().getName() + " 做了一碗面");
                    Desk.foodflag = 1;
                    // 通知消費者可以消費了
                    Desk.lock.notifyAll();
                }
            }
        }
        System.out.println(Thread.currentThread().getName() + " 停止生產(chǎn)");
    }
}

3. Foodie.java(消費者線程)

/**
 * 消費者線程 - 吃貨
 */
public class Foodie extends Thread {
    @Override
    public void run() {
        while (true) {
            synchronized (Desk.lock) {
                // 如果食物已全部消費完,則退出
                if (Desk.count == 0) {
                    Desk.lock.notifyAll();  // 確保生產(chǎn)者線程能退出
                    break;
                }
                
                // 如果沒有食物,則等待
                if (Desk.foodflag == 0) {
                    try {
                        Desk.lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    // 消費食物
                    Desk.count--;
                    System.out.println(Thread.currentThread().getName() + " 吃了一碗,還剩 " + Desk.count + " 碗");
                    Desk.foodflag = 0;
                    // 通知生產(chǎn)者可以生產(chǎn)了
                    Desk.lock.notifyAll();
                }
            }
        }
        System.out.println(Thread.currentThread().getName() + " 停止消費");
    }
}

4. Main.java(測試類)

/**
 * 測試類
 */
public class Main {
    public static void main(String[] args) {
        // 創(chuàng)建并啟動生產(chǎn)者線程
        Cook cook = new Cook();
        cook.setName("廚師");
        
        // 創(chuàng)建并啟動消費者線程
        Foodie foodie = new Foodie();
        foodie.setName("吃貨");
        
        cook.start();
        foodie.start();
    }
}

關(guān)鍵點解析

1. 同步機制

我們使用synchronized關(guān)鍵字實現(xiàn)對共享資源的互斥訪問:

synchronized (Desk.lock) {
    // 臨界區(qū)代碼
}

2. 線程通信

通過wait()notifyAll()實現(xiàn)線程間協(xié)作:

  • wait():釋放鎖并進入等待狀態(tài)

  • notifyAll():喚醒所有等待該鎖的線程

3. 生產(chǎn)消費邏輯

  • 生產(chǎn)者檢查foodflag

    • 為0時生產(chǎn)食物并設置foodflag=1

    • 為1時等待消費者消費

  • 消費者檢查foodflag

    • 為1時消費食物并設置foodflag=0

    • 為0時等待生產(chǎn)者生產(chǎn)

執(zhí)行結(jié)果示例

廚師 做了一碗面
吃貨 吃了一碗,還剩 9 碗
廚師 做了一碗面
吃貨 吃了一碗,還剩 8 碗
...
吃貨 吃了一碗,還剩 0 碗
廚師 停止生產(chǎn)
吃貨 停止消費

常見問題解答

Q1: 為什么使用notifyAll()而不是notify()?

notifyAll()會喚醒所有等待線程,讓它們公平競爭鎖,避免某些線程長期得不到執(zhí)行的情況。而notify()只隨機喚醒一個線程,可能導致線程饑餓。

Q2: 為什么要在finally塊外調(diào)用notifyAll()?

因為notifyAll()必須在持有鎖的情況下調(diào)用,而synchronized塊結(jié)束時鎖會自動釋放,所以不需要在finally中調(diào)用。

Q3: 如何避免死鎖?

  • 確保每個wait()都有對應的notifyAll()

  • 設置合理的退出條件(如count == 0

  • 避免嵌套鎖

總結(jié)

通過這個案例,我們學習了:

  • 如何使用synchronized實現(xiàn)線程同步

  • 如何使用wait()/notifyAll()實現(xiàn)線程通信

  • 生產(chǎn)者-消費者模型的經(jīng)典實現(xiàn)

  • 多線程編程中的常見問題及解決方案

這個模型可以應用于許多實際場景,如消息隊列、任務調(diào)度等系統(tǒng)設計中。

到此這篇關(guān)于Java生產(chǎn)者和消費者實現(xiàn)等待喚醒機制的文章就介紹到這了,更多相關(guān)Java 等待喚醒機制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • mybatis錯誤之in查詢?<foreach>循環(huán)問題

    mybatis錯誤之in查詢?<foreach>循環(huán)問題

    這篇文章主要介紹了mybatis錯誤之in查詢?<foreach>循環(huán)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • MyBatis-Flex實現(xiàn)分頁查詢的示例代碼

    MyBatis-Flex實現(xiàn)分頁查詢的示例代碼

    在MyBatis-Flex中實現(xiàn)分頁查詢時,需要注意維護一個獲取數(shù)據(jù)庫總數(shù)的方法,詳細介紹了UserService、UserServiceImpl類以及Mapper.xml配置,感興趣的可以了解一下
    2024-10-10
  • 利用java、js或mysql計算高德地圖中兩坐標之間的距離

    利用java、js或mysql計算高德地圖中兩坐標之間的距離

    最近因為工作的需求,需要計算出高德地圖中兩個坐標的距離,通過查找相關(guān)資料發(fā)現(xiàn)了多種實現(xiàn)的方法,下面這篇文章主要給大家介紹了關(guān)于利用java、js或mysql計算高德地圖中兩坐標之間距離的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下。
    2017-10-10
  • java:java.lang.ExceptionInInitializerError報錯解決過程

    java:java.lang.ExceptionInInitializerError報錯解決過程

    這篇文章主要給大家介紹了關(guān)于java:java.lang.ExceptionInInitializerError報錯的解決過程,java.lang.ExceptionInInitializerError 是一個異常,表示在初始化一個類的靜態(tài)變量或靜態(tài)塊時發(fā)生了錯誤,需要的朋友可以參考下
    2023-10-10
  • Java編譯和解釋執(zhí)行對比及原理解析

    Java編譯和解釋執(zhí)行對比及原理解析

    這篇文章主要介紹了Java編譯和解釋執(zhí)行對比及原理解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-05-05
  • 詳解如何使用SpringBoot封裝Excel生成器

    詳解如何使用SpringBoot封裝Excel生成器

    在軟件開發(fā)過程中,經(jīng)常需要生成Excel文件來導出數(shù)據(jù)或者生成報表,為了簡化開發(fā)流程和提高代碼的可維護性,我們可以使用Spring Boot封裝Excel生成器,本文將介紹如何使用Spring Boot封裝Excel生成器,并提供一些示例代碼來說明其用法和功能
    2023-06-06
  • Java簡單使用redis-zset實現(xiàn)排行榜

    Java簡單使用redis-zset實現(xiàn)排行榜

    這篇文章主要介紹了Java簡單使用redis-zset實現(xiàn)排行榜,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-12-12
  • 在Java內(nèi)存模型中測試并發(fā)程序代碼

    在Java內(nèi)存模型中測試并發(fā)程序代碼

    這篇文章主要介紹了在Java內(nèi)存模型中測試并發(fā)程序代碼,輔以文中所提到的JavaScript庫JCStress進行,需要的朋友可以參考下
    2015-07-07
  • 逆序?qū)栴}(Java實現(xiàn))歸并詳解

    逆序?qū)栴}(Java實現(xiàn))歸并詳解

    文章介紹了計算給定正整數(shù)序列中逆序?qū)?shù)量的方法,特別是使用歸并排序進行拆分和合并時統(tǒng)計逆序?qū)?通過遞歸拆分序列,并在合并過程中統(tǒng)計逆序?qū)?shù)量,從而得到整個序列的逆序?qū)倲?shù),此方法能有效處理包含重復數(shù)字的序列
    2026-05-05
  • Spring之什么是ObjectFactory?什么是ObjectProvider?

    Spring之什么是ObjectFactory?什么是ObjectProvider?

    這篇文章主要介紹了Spring之什么是ObjectFactory?什么是ObjectProvider?具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01

最新評論

万荣县| 新乡市| 扎赉特旗| 平阴县| 沙湾县| 长葛市| 四会市| 三河市| 嘉祥县| 屏南县| 武鸣县| 黑水县| 平舆县| 镇宁| 都安| 蒲城县| 普格县| 沙湾县| 朝阳县| 定西市| 鹤壁市| 宁陕县| 阳春市| 尖扎县| 黔西| 福泉市| 姚安县| 枣强县| 定西市| 游戏| 广州市| 靖西县| 丽江市| 堆龙德庆县| 榕江县| 汶上县| 临汾市| 渭源县| 永福县| 邯郸县| 遂昌县|