五、線程之間的協(xié)作

一、典型例子:生產(chǎn)者消費(fèi)者

自行百度,不作贅述

二、業(yè)務(wù)場景

當(dāng)A線程對一個變量進(jìn)行修改,然后通知其他線程之后,B線程根據(jù)這個通知進(jìn)行觸發(fā)相應(yīng)的業(yè)務(wù)邏輯。
最笨的方法:我們首先會在B線程中:

while(條件不滿足){
  check 條件不滿足
  sleep(50);
}

但是這種做法有個問題,不能保證業(yè)務(wù)變化的及時性,即可能我剛開始休眠這個條件就已經(jīng)滿足了還需要等待固定的時間,有人就說:那我可以把休眠時間調(diào)整的盡可能小,那么對于我們的CPU的負(fù)載壓力就很大了,因此這種方式是有弊端的。

wait()

當(dāng)A線程的O對象調(diào)用wait()方法之后,進(jìn)入等待狀態(tài),只有當(dāng)B線程調(diào)用O對象的notify()或notifyAll()方法之后才會喚醒A線程。A喚醒之后做自己的相關(guān)業(yè)務(wù)工作。

notify()和notifyAll()

如果某些線程在等待某些條件觸發(fā),那當(dāng)那些條件為真時,你可以用 notify 和 notifyAll 來通知那些等待中的線程重新開始運(yùn)行。不同之處在于,notify 僅僅通知一個線程,并且我們不知道哪個線程會收到通知,然而 notifyAll 會通知所有等待中的線程。換言之,如果只有一個線程在等待一個信號燈,notify和notifyAll都會通知到這個線程。但如果多個線程在等待這個信號燈,那么notify只會通知到其中一個,而其它線程并不會收到任何通知,而notifyAll會喚醒所有等待中的線程。

三、等待和通知的標(biāo)準(zhǔn)范式

等待方要進(jìn)行等待時:

syn(對象){
    while(條件不滿足){
        對象.wait()
    }
    條件滿足了,做業(yè)務(wù)邏輯
}

通知方:

syn(對象){
    改變條件
    對象.notify()/notifyAll()
}

四、notify()和notifyAll()應(yīng)該用誰

notify()具有隨機(jī)性,因?yàn)椴恢酪獑拘涯囊粋€,所以在不確定要喚醒具體哪個線程的時候,最好是用notifyAll(),謹(jǐn)慎使用notify()。

五、市面上所有的連接池都是通過等待超時模式實(shí)現(xiàn)的

一個連接池中有固定的(比如10個)連接數(shù),如果在某一時刻并發(fā)量上來了,有50個請求需要訪問數(shù)據(jù)庫,那么只會有十個請求去成功地訪問到數(shù)據(jù)庫中,剩下的40個線程會進(jìn)入到一個等待狀態(tài),只有當(dāng)十個已經(jīng)連接數(shù)據(jù)庫的線程的業(yè)務(wù)處理完畢,釋放掉數(shù)據(jù)庫的連接,才會去通知剩余的40個線程,然后從剩余的40個連接中挑一個線程去進(jìn)行數(shù)據(jù)庫的連接。

六、調(diào)用yield()、sleep()、wait()、notify()等方法對鎖有何影響?

調(diào)用yield()、sleep()之后,當(dāng)前線程所持有的鎖是不會被釋放的
調(diào)用wait()方法之后會釋放當(dāng)前線程鎖持有的鎖,被喚醒之后會重新競爭鎖。
調(diào)用notify()后對鎖沒有任何影響,但是在調(diào)用notify()時,一定要放在一個同步塊里面,線程只有在執(zhí)行完整個同步塊后,才會自然而然釋放鎖,因此notify()一般放在代碼同步塊的最后一行。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容