Java并發(fā)——線程間協(xié)作(wait、notify、sleep、yield、join)

1 線程的狀態(tài)

Java中線程中狀態(tài)可分為五種:New(新建狀態(tài)),Runnable(就緒狀態(tài)),Running(運行狀態(tài)),Blocked(阻塞狀態(tài)),Dead(死亡狀態(tài))。

  • New:新建狀態(tài),當線程創(chuàng)建完成時為新建狀態(tài),即new Thread(...),還沒有調(diào)用start方法時,線程處于新建狀態(tài)
  • Runnable:就緒狀態(tài),當調(diào)用線程的的start方法后,線程進入就緒狀態(tài),等待CPU資源。處于就緒狀態(tài)的線程由Java運行時系統(tǒng)的線程調(diào)度程序(thread scheduler)來調(diào)度
  • Running:運行狀態(tài),就緒狀態(tài)的線程獲取到CPU執(zhí)行權(quán)以后進入運行狀態(tài),開始執(zhí)行run方法
  • Blocked:阻塞狀態(tài),線程沒有執(zhí)行完,由于某種原因(如,I/O操作等)讓出CPU執(zhí)行權(quán),自身進入阻塞狀態(tài)
  • Dead:死亡狀態(tài),線程執(zhí)行完成或者執(zhí)行過程中出現(xiàn)異常,線程就會進入死亡狀態(tài)。

這五種狀態(tài)之間的轉(zhuǎn)換關系如下圖所示:

這里寫圖片描述

2 wait

JDK中一共提供了這三個版本的方法

  • wait()方法的作用是將當前運行的線程掛起(即讓其進入阻塞狀態(tài)),直到notify或notifyAll方法來喚醒線程
  • wait(long timeout),該方法與wait()方法類似,唯一的區(qū)別就是在指定時間內(nèi),如果沒有notify或notifAll方法的喚醒,也會自動喚醒
  • wait(long timeout,long nanos),在于更精確的控制調(diào)度時間

wait方法的使用必須在同步的范圍內(nèi),否則就會拋出IllegalMonitorStateException異常,wait方法的作用就是阻塞當前線程等待notify/notifyAll方法的喚醒,或等待超時后自動喚醒。

3 notify/notifyAll

有了對wait方法原理的理解,notify方法和notifyAll方法就很容易理解了。既然wait方式是通過對象的monitor對象來實現(xiàn)的,所以只要在同一對象上去調(diào)用notify/notifyAll方法,就可以喚醒對應對象monitor上等待的線程了。notify和notifyAll的區(qū)別在于前者只能喚醒monitor上的一個線程,對其他線程沒有影響,而notifyAll則喚醒所有的線程。

4 sleep/yield/join

4.1 sleep

sleep方法的作用是讓當前線程暫停指定的時間(毫秒),sleep方法是最簡單的方法,在上述的例子中也用到過,比較容易理解。唯一需要注意的是其與wait方法的區(qū)別。最簡單的區(qū)別是,wait方法依賴于同步,而sleep方法可以直接調(diào)用。而更深層次的區(qū)別在于sleep方法只是暫時讓出CPU的執(zhí)行權(quán),并不釋放鎖。而wait方法則需要釋放鎖。

sleep暫停期間一直持有monitor對象鎖,其他線程是不能進入的。而wait方法則不同,當調(diào)用wait方法后,當前線程會釋放持有的monitor對象鎖,因此,其他線程還可以進入到同步方法,線程被喚醒后,需要競爭鎖,獲取到鎖之后再繼續(xù)執(zhí)行。

4.2 yield

yield方法的作用是暫停當前線程,以便其他線程有機會執(zhí)行,不過不能指定暫停的時間,并且也不能保證當前線程馬上停止。yield方法只是將Running狀態(tài)轉(zhuǎn)變?yōu)镽unnable狀態(tài)。

4.3 join

join方法的作用是父線程等待子線程執(zhí)行完成后再執(zhí)行,換句話說就是將異步執(zhí)行的線程合并為同步的線程。JDK中提供三個版本的join方法,其實現(xiàn)與wait方法類似,join()方法實際上執(zhí)行的join(0),而join(long millis, int nanos)也與wait(long millis, int nanos)的實現(xiàn)方式一致,暫時對納秒的支持也是不完整的。

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

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

  • 本文出自 Eddy Wiki ,轉(zhuǎn)載請注明出處:http://eddy.wiki/interview-java.h...
    eddy_wiki閱讀 2,298評論 0 14
  • 該文章轉(zhuǎn)自:http://blog.csdn.net/evankaka/article/details/44153...
    加來依藍閱讀 7,469評論 3 87
  • 本文主要講了java中多線程的使用方法、線程同步、線程數(shù)據(jù)傳遞、線程狀態(tài)及相應的一些線程函數(shù)用法、概述等。 首先講...
    李欣陽閱讀 2,597評論 1 15
  • 1.解決信號量丟失和假喚醒 public class MyWaitNotify3{ MonitorObject m...
    Q羅閱讀 1,005評論 0 1
  • 【一】如果冬天我已熟稔我將用詞語上的秋季改寫那些月份以果實的定義重新敘說月光沉甸甸的白,一枚熟透的冬之芬芳行人道上...
    梧鳴閱讀 497評論 0 5

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