更新時間:2017-11-14 來源:黑馬程序員 瀏覽量:
任何對象都有生命周期,線程也不例外,它也有自己的生命周期。線程的整個生命周期分為六個階段,分別是新建狀態(New)、可運行狀態(Runnable)、運行狀態(Running)、阻塞狀態(Blocked)、等待狀態(Waiting)和死亡狀態(Terminated),線程的不同狀態表明了線程當前正在進行的活動(有些地方把等待狀態分為兩種,加了一個定時等待Timed-Waiting)。
下面對線程生命周期中的六種狀態進行詳細說明。
1. 新建狀態(New)
創建一個線程對象后,該線程對象就處于新建狀態,此時它不能運行,和其它Java對象一樣,僅僅由Java虛擬機為其分配了內存,沒有表現出任何線程的動態特征。
2. 可運行狀態(Runnable)
當線程對象調用了start()方法后,該線程就進入可運行狀態。處于可運行狀態的線程位于可運行池中,此時它只是具備了運行的條件,能否獲得CPU的使用權開始運行,還需要等待系統的調度。
3. 運行狀態(Running)
如果處于可運行狀態的線程獲得了CPU的使用權,開始執行run()方法中的線程執行體,則該線程處于運行狀態。當一個線程啟動后,它不可能一直處于運行狀態(除非它的線程執行體足夠短,瞬間就結束了),系統會為每一個線程分配一小段的時間來處理任務,當線程用完了這段時間,系統就會剝奪該線程占用的CPU資源,讓其它線程獲得執行的機會。需要注意的是,只有處于可運行狀態的線程才可能轉換到運行狀態。
4. 阻塞狀態(Blocked)和等待狀態(Waiting)
如果線程由于某些原因放棄了CPU的的使用權,暫時停止運行,此線程就進入了阻塞或者等待狀態,阻塞或者等待狀態都是由運行狀態轉換而來的。下面列舉出線程進入阻塞狀態或等待狀態的原因。
線程進入阻塞的原因:
l 線程試圖獲取某個對象的同步鎖,而該鎖被其它線程持有
l 當線程調用了一個阻塞式的IO方法
線程進入等待狀態原因:
l 線程調用了某個對象的wait()方法
l 線程調用了Thread的sleep(longmillis)方法
l 線程調用了另一個線程的join()方法
當正在執行的線程進入阻塞或者等待狀態后,其它處于可運行狀態的線程就可以獲得執行的機會。被阻塞或者等待的線程會在適當的時候重新進入可運行狀態,等待系統的調度。下面列舉出線程由阻塞狀態或等待狀態進入可運行狀態的時機。
線程由阻塞狀態進入可運行狀態的時機:
l 線程成功地獲取了某個對象的同步鎖
l 阻塞式的IO方法已經返回
線程由等待狀態進入可運行狀態的時機:
l 其它線程調用了某個對象的notify()或者notifyAll()方法
l Thread的sleep(longmillis)方法經過了指定的時間
l 調用join()方法的線程執行完畢
需要注意的是,線程從阻塞或者等待狀態只能進入可運行狀態,而不能直接進入運行狀態,也就是說,結束阻塞和等待的線程需要重新進入可運行池中,等待系統的調度。
5. 死亡狀態(Terminated)
線程的run()方法正常執行完畢或者線程拋出一個未捕獲的異常(Exception)、錯誤(Error),線程就進入死亡狀態。一旦進入死亡狀態,線程將不再擁有運行的資格,也不能再轉換到其它的狀態。
通過上面的講解,大家對線程的各種狀態以及狀態之間的轉換條件都有了詳細的了解,下面通過一張圖更清楚的描述這流中狀態的轉換關系:友情提示:獲得更多學科學習視頻+資料+源碼,請加QQ:3276250747。
本文版權歸黑馬程序員JavaEE學院所有,歡迎轉載,轉載請注明作者出處。謝謝!
作者:黑馬程序員JavaEE培訓學院
首發:http://java.itheima.com/