多線程通訊的api:
wait 和notify、notifyAll
原理:
wait的實現(xiàn)原理是利用對象的等待隊列,執(zhí)行的時候會給鎖的對象的等待隊列加一條,執(zhí)行的時候會釋放當(dāng)前鎖,讓其他線程正常調(diào)用鎖對象。
注意:
- 都應(yīng)該在synchronize代碼塊中執(zhí)行,否則會報錯,跟內(nèi)部機(jī)制有關(guān)系。
- wait的執(zhí)行時機(jī)很重要,一定要確保在其他線程notify之前wait,否則就會出現(xiàn)邏輯問題,一直wait的情況。
- 官方建議判斷是否進(jìn)入等待狀態(tài)應(yīng)該在循環(huán)中檢查(while),而不應(yīng)該用if判斷,原因是底層“偽喚醒”的問題會導(dǎo)致程序執(zhí)行沒有notify或者unpark就被喚醒。
park 和unpark
原理:
利用的是令牌機(jī)制,park負(fù)責(zé)等待,一次消耗一個令牌,unpark負(fù)責(zé)發(fā)令牌,一次發(fā)一個,park、unpark沒有次序問題,但是要注意一個unpark只能發(fā)一個令牌,如果調(diào)用了多次park還是會一直等待。
注意:
- unpark需要指定thread對象
LockSupport.park();
LockSupport.unpark(someThread); - park的內(nèi)部機(jī)制不是通過鎖的監(jiān)視,而是直接掛起線程,因此不能放到synchronize代碼塊中,因為park不會釋放鎖,這樣會導(dǎo)致代碼塊永遠(yuǎn)不會被執(zhí)行。
- 官方建議判斷是否進(jìn)入等待狀態(tài)應(yīng)該在循環(huán)中檢查(while),而不應(yīng)該用if判斷,原因是底層“偽喚醒”的問題會導(dǎo)致程序執(zhí)行沒有notify或者unpark就被喚醒。