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

一文詳解Java?Condition的await和signal等待通知機(jī)制

 更新時(shí)間:2025年02月06日 08:18:52   作者:Cosolar  
這篇文章主要為大家詳細(xì)介紹了Java?Condition的await和signal等待通知機(jī)制的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下

我現(xiàn)在得仔細(xì)理解Java中Condition的await和signal機(jī)制。首先,我知道Java里處理并發(fā)問(wèn)題通常會(huì)用到synchronized關(guān)鍵字和Object的wait()、notify()方法。但后來(lái)引入了Lock和Condition,提供了更靈活的線程同步方式。那Condition到底是怎么工作的呢?特別是await和signal這兩個(gè)方法。

Java中的Condition接口提供了比傳統(tǒng)synchronized配合wait()notify()更靈活的線程等待/通知機(jī)制。結(jié)合Lock使用,Condition允許更細(xì)粒度的線程控制。以下是其核心機(jī)制與使用要點(diǎn)的總結(jié):

1. Condition的核心方法

  • await():釋放當(dāng)前鎖,使線程進(jìn)入等待狀態(tài),直到以下情況發(fā)生:
    • signal()signalAll()喚醒。
    • 線程被中斷(拋出InterruptedException)。
    • 支持超時(shí)或指定截止時(shí)間的變體方法(如awaitNanos()、awaitUntil())。
  • signal():?jiǎn)拘岩粋€(gè)等待在此Condition上的線程(隨機(jī)選擇)。
  • signalAll():?jiǎn)拘阉械却诖?code>Condition上的線程。

2. 使用場(chǎng)景與優(yōu)勢(shì)

  • 多條件變量:一個(gè)Lock可關(guān)聯(lián)多個(gè)Condition,每個(gè)條件代表不同的等待條件(如生產(chǎn)者-消費(fèi)者模型中的“隊(duì)列非空”和“隊(duì)列未滿”)。
  • 精準(zhǔn)喚醒:避免無(wú)意義的線程競(jìng)爭(zhēng)(如生產(chǎn)者只喚醒消費(fèi)者,而非其他生產(chǎn)者)。
  • 靈活性:支持中斷、超時(shí)和非阻塞嘗試等待。

3. 使用流程與規(guī)范

那么,在生產(chǎn)者-消費(fèi)者模型中如何應(yīng)用呢?假設(shè)我們有一個(gè)有限容量的隊(duì)列,當(dāng)隊(duì)列滿時(shí),生產(chǎn)者線程需要等待notFull條件;當(dāng)隊(duì)列空時(shí),消費(fèi)者線程需要等待notEmpty條件。生產(chǎn)者生產(chǎn)一個(gè)元素后,會(huì)signal notEmpty條件,喚醒消費(fèi)者;消費(fèi)者消費(fèi)一個(gè)元素后,會(huì)signal notFull條件,喚醒生產(chǎn)者。這樣的實(shí)現(xiàn)會(huì)比使用synchronized更高效,因?yàn)槊看螁拘训木€程都是確實(shí)需要被喚醒的,而不是所有線程都被喚醒。

基本模板

Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();

lock.lock();
try {
    while (條件不滿足) { // 必須用while循環(huán)檢查條件,防止虛假喚醒
        condition.await();
    }
    // 執(zhí)行業(yè)務(wù)邏輯
} catch (InterruptedException e) {
    // 處理中斷
} finally {
    lock.unlock();
}

生產(chǎn)者-消費(fèi)者示例

class BoundedBuffer {
    final Lock lock = new ReentrantLock();
    final Condition notFull = lock.newCondition();  // 隊(duì)列未滿條件
    final Condition notEmpty = lock.newCondition(); // 隊(duì)列非空條件

    final Object[] items = new Object[100];
    int putPtr, takePtr, count;

    public void put(Object x) throws InterruptedException {
        lock.lock();
        try {
            while (count == items.length) // 隊(duì)列滿,等待非滿條件
                notFull.await();
            items[putPtr] = x;
            if (++putPtr == items.length) putPtr = 0;
            count++;
            notEmpty.signal(); // 生產(chǎn)后喚醒消費(fèi)者
        } finally {
            lock.unlock();
        }
    }

    public Object take() throws InterruptedException {
        lock.lock();
        try {
            while (count == 0) // 隊(duì)列空,等待非空條件
                notEmpty.await();
            Object x = items[takePtr];
            if (++takePtr == items.length) takePtr = 0;
            count--;
            notFull.signal(); // 消費(fèi)后喚醒生產(chǎn)者
            return x;
        } finally {
            lock.unlock();
        }
    }
}

這里,使用signal還是signalAll要看具體情況。如果每次生產(chǎn)或消費(fèi)一個(gè)元素,只需要喚醒一個(gè)對(duì)應(yīng)的消費(fèi)者或生產(chǎn)者,那么signal足夠,效率更高。但如果存在多個(gè)消費(fèi)者或生產(chǎn)者可能同時(shí)滿足條件,可能需要用signalAll來(lái)避免死鎖或者保證所有可能被喚醒的線程都能繼續(xù)執(zhí)行。

不過(guò),使用signalAll可能會(huì)導(dǎo)致“驚群效應(yīng)”,即多個(gè)線程被喚醒但只有一個(gè)能繼續(xù)執(zhí)行,其他線程又進(jìn)入等待。這時(shí)候可能影響性能。所以要根據(jù)具體情況選擇。

另外,需要注意,調(diào)用signal或signalAll的時(shí)候,必須持有對(duì)應(yīng)的鎖,否則會(huì)拋出IllegalMonitorStateException。這是因?yàn)檫@些方法需要修改條件變量的狀態(tài),而這些狀態(tài)通常由鎖保護(hù),所以必須在鎖的范圍內(nèi)調(diào)用。

4. 關(guān)鍵注意事項(xiàng)

  • 鎖的持有:調(diào)用await()、signal()signalAll()前必須持有對(duì)應(yīng)的鎖,否則拋出IllegalMonitorStateException。
  • 循環(huán)檢查條件:使用while而非if檢查條件,防止虛假喚醒(Spurious Wakeup)。
  • 中斷處理await()可能被中斷,需捕獲InterruptedException并妥善處理。
  • signal選擇:優(yōu)先使用signal()減少競(jìng)爭(zhēng),但需確保邏輯正確性;在復(fù)雜場(chǎng)景或不確定時(shí)使用signalAll()。

然后是signal和signalAll方法。signal()會(huì)喚醒一個(gè)等待在Condition上的線程,而signalAll()會(huì)喚醒所有等待的線程。這和notify()、notifyAll()類似。不過(guò)因?yàn)镃ondition可以有多個(gè),所以喚醒的線程可能是針對(duì)某個(gè)特定條件的。比如,當(dāng)生產(chǎn)者生產(chǎn)了一個(gè)物品后,調(diào)用隊(duì)列不空條件的signal,這樣只有消費(fèi)者線程會(huì)被喚醒,而生產(chǎn)者線程可能在其他條件上等待,不會(huì)被影響。這樣就提高了效率,減少無(wú)意義的線程競(jìng)爭(zhēng)。

5. 與傳統(tǒng)機(jī)制的對(duì)比

我記得Lock替代了synchronized,而Condition替代了Object的監(jiān)視器方法。每個(gè)Lock可以有多個(gè)Condition,這樣不同的條件變量可以更精確地控制線程的等待和喚醒。比如說(shuō),一個(gè)生產(chǎn)者-消費(fèi)者模型里,可能有兩個(gè)條件,一個(gè)代表隊(duì)列不滿,另一個(gè)代表隊(duì)列不空。這樣生產(chǎn)者和消費(fèi)者可以分別在不同的條件上等待,避免像用Object的wait/notify時(shí)所有線程都在同一個(gè)條件上競(jìng)爭(zhēng),導(dǎo)致不必要的喚醒。

特性synchronized + wait()/notify()Lock + Condition
鎖獲取方式隱式獲取/釋放顯式調(diào)用lock()和unlock()
條件變量數(shù)量每個(gè)對(duì)象僅一個(gè)等待隊(duì)列一個(gè)Lock可關(guān)聯(lián)多個(gè)Condition
超時(shí)/中斷支持有限支持超時(shí)、截止時(shí)間和不可中斷模式
靈活性簡(jiǎn)單但不夠靈活更細(xì)粒度的線程控制

那await方法的作用是什么呢?當(dāng)線程調(diào)用await()時(shí),應(yīng)該會(huì)釋放鎖,并進(jìn)入等待狀態(tài),直到被signal喚醒或者被中斷。這里可能需要和Object的wait()對(duì)比,await()同樣會(huì)釋放鎖,但需要結(jié)合Lock使用。調(diào)用await()前必須持有對(duì)應(yīng)的鎖,否則會(huì)拋出異常,比如IllegalMonitorStateException。那Condition的await()方法可能更靈活,因?yàn)樗梢员淮驍?,或者設(shè)置超時(shí)時(shí)間,比如awaitUninterruptibly()、awaitNanos()等方法,提供了更多控制選項(xiàng)。

6. 總結(jié)

Condition的await和signal機(jī)制提供了比傳統(tǒng)wait/notify更靈活和高效的線程通信方式。通過(guò)多個(gè)條件變量,可以精確控制線程的喚醒,減少不必要的競(jìng)爭(zhēng)和上下文切換,提升并發(fā)性能。使用時(shí)需要注意正確管理鎖,循環(huán)檢查條件,處理中斷,以及合理選擇signal或signalAll。

Conditionawaitsignal機(jī)制通過(guò)多條件變量和顯式鎖控制,顯著提升了線程協(xié)作的效率和靈活性。適用于需要精確喚醒或復(fù)雜同步邏輯的場(chǎng)景(如線程池、阻塞隊(duì)列)。正確使用時(shí)需遵循鎖的規(guī)范,合理處理?xiàng)l件檢查與喚醒策略。

到此這篇關(guān)于一文詳解Java Condition的await和signal等待通知機(jī)制的文章就介紹到這了,更多相關(guān)Java Condition等待通知機(jī)制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 解決mybatis-plus新增數(shù)據(jù)自增ID變無(wú)序問(wèn)題

    解決mybatis-plus新增數(shù)據(jù)自增ID變無(wú)序問(wèn)題

    這篇文章主要介紹了解決mybatis-plus新增數(shù)據(jù)自增ID變無(wú)序問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。
    2023-07-07
  • java 文件大數(shù)據(jù)Excel下載實(shí)例代碼

    java 文件大數(shù)據(jù)Excel下載實(shí)例代碼

    這篇文章主要介紹了java 文件大數(shù)據(jù)Excel下載實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • Java?NIO?中Buffer?緩沖區(qū)解析

    Java?NIO?中Buffer?緩沖區(qū)解析

    這篇文章主要介紹了Java?NIO?中Buffer?緩沖區(qū),Java?NIO?中的?Buffer?用于和?NIO?通道進(jìn)行交互。數(shù)據(jù)是通道讀取到緩沖區(qū),從緩沖區(qū)寫入到通道中的。下面內(nèi)容希望幫助帶大家理解
    2022-02-02
  • 詳解Java動(dòng)態(tài)字節(jié)碼技術(shù)

    詳解Java動(dòng)態(tài)字節(jié)碼技術(shù)

    Java字節(jié)碼增強(qiáng)指的是在Java字節(jié)碼生成之后,對(duì)其進(jìn)行修改,增強(qiáng)其功能,可減少冗余代碼,提高性能等。本文將詳細(xì)介紹Java動(dòng)態(tài)字節(jié)碼技術(shù)。
    2021-05-05
  • MyBatis-Plus實(shí)現(xiàn)字段自動(dòng)填充功能的示例

    MyBatis-Plus實(shí)現(xiàn)字段自動(dòng)填充功能的示例

    本文主要介紹了MyBatis-Plus實(shí)現(xiàn)字段自動(dòng)填充功能的示例,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • Java中零拷貝和深拷貝的原理及實(shí)現(xiàn)探究(代碼示例)

    Java中零拷貝和深拷貝的原理及實(shí)現(xiàn)探究(代碼示例)

    深拷貝和零拷貝是兩個(gè)在 Java 中廣泛使用的概念,它們分別用于對(duì)象復(fù)制和數(shù)據(jù)傳輸優(yōu)化,下面將詳細(xì)介紹這兩個(gè)概念的原理,并給出相應(yīng)的 Java 代碼示例,感興趣的朋友一起看看吧
    2023-12-12
  • Spring Cloud Alibaba Nacos Config進(jìn)階使用

    Spring Cloud Alibaba Nacos Config進(jìn)階使用

    這篇文章主要介紹了Spring Cloud Alibaba Nacos Config進(jìn)階使用,文中使用企業(yè)案例,圖文并茂的展示了Nacos Config的使用,感興趣的小伙伴可以看一看
    2021-08-08
  • 從零開始講解Java微信公眾號(hào)消息推送實(shí)現(xiàn)

    從零開始講解Java微信公眾號(hào)消息推送實(shí)現(xiàn)

    微信公眾號(hào)分為訂閱號(hào)和服務(wù)號(hào),無(wú)論有沒(méi)有認(rèn)證,訂閱號(hào)每天都能推送一條消息,也就是每天只能推送一次消息給粉絲,這篇文章主要給大家介紹了關(guān)于Java微信公眾號(hào)消息推送實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下
    2022-09-09
  • Java超詳細(xì)講解接口的實(shí)現(xiàn)與用法

    Java超詳細(xì)講解接口的實(shí)現(xiàn)與用法

    Java接口是一系列方法的聲明,是一些方法特征的集合,一個(gè)接口只有方法的特征沒(méi)有方法的實(shí)現(xiàn),因此這些方法可以在不同的地方被不同的類實(shí)現(xiàn),而這些實(shí)現(xiàn)可以具有不同的行為
    2022-04-04
  • Java遍歷起止日期中間的所有日期操作

    Java遍歷起止日期中間的所有日期操作

    這篇文章主要介紹了Java遍歷起止日期中間的所有日期操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-09-09

最新評(píng)論

河津市| 会宁县| 政和县| 拉孜县| 滕州市| 新昌县| 聂拉木县| 湘乡市| 江孜县| 建瓯市| 读书| 海口市| 新巴尔虎右旗| 榆树市| 黔江区| 沅江市| 顺昌县| 确山县| 灵丘县| 宁城县| 芜湖市| 高安市| 滦平县| 鹰潭市| 青岛市| 哈尔滨市| 沅江市| 资兴市| 信丰县| 马山县| 汉沽区| 卓尼县| 锡林郭勒盟| 祁门县| 额尔古纳市| 亚东县| 民县| 北海市| 六安市| 同江市| 扎兰屯市|