Java:線程的六種狀態及轉化

前文傳送門:多線程概述及建立方式java

Java:線程的六種狀態及轉化

關於線程的生命週期,網上書上說法不一,難以統一,本篇作一個總結:編程

java.lang.Thread.State枚舉類中定義了六種線程的狀態,能夠調用線程Thread中的getState()方法獲取當前線程的狀態多線程

線程狀態 解釋
NEW 還沒有啓動的線程狀態,即線程建立,還未調用start方法
RUNNABLE 就緒狀態(調用start,等待調度)+正在運行
BLOCKED 等待監視器鎖時,陷入阻塞狀態
WAITING 等待狀態的線程正在等待另外一線程執行特定的操做(如notify)
TIMED_WAITING 具備指定等待時間的等待狀態
TERMINATED 線程完成執行,終止狀態

下圖源自《Java併發編程藝術》圖4-1
併發

1、新建狀態(NEW)

即用new關鍵字新建一個線程,這個線程就處於新建狀態this

2、運行狀態(RUNNABLE)

操做系統中的就緒和運行兩種狀態,在Java中統稱爲RUNNABLE。操作系統

就緒狀態(READY)

當線程對象調用了start()方法以後,線程處於就緒狀態,就緒意味着該線程能夠執行,但具體啥時候執行將取決於JVM裏線程調度器的調度。線程

It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution.rest

  • 不容許對一個線程屢次使用start。code

  • 線程執行完成以後,不能試圖用start將其喚醒。

其餘狀態 ->就緒

  • 線程調用start(),新建狀態轉化爲就緒狀態。
  • 線程sleep(long)時間到,等待狀態轉化爲就緒狀態。
  • 阻塞式IO操做結果返回,線程變爲就緒狀態。
  • 其餘線程調用join()方法,結束以後轉化爲就緒狀態。
  • 線程對象拿到對象鎖以後,也會進入就緒狀態。

運行狀態(RUNNING)

處於就緒狀態的線程得到了CPU以後,真正開始執行run()方法的線程執行體時,意味着該線程就已經處於運行狀態。須要注意的是,對於單處理器,一個時刻只能有一個線程處於運行狀態。
對於搶佔式策略的系統來講,系統會給每一個線程一小段時間處理各自的任務。時間用完以後,系統負責奪回線程佔用的資源。下一段時間裏,系統會根據必定規則,再次進行調度。

運行狀態轉變爲就緒狀態的情形:

  • 線程失去處理器資源。線程不必定完整執行的,執行到一半,說不定就被別的線程搶走了。
  • 調用yield()靜態方法,暫時暫停當前線程,讓系統的線程調度器從新調度一次,它本身徹底有可能再次運行。

yield方法的官方解釋:

A hint to the scheduler that the current thread is willing to yield its current use of a processor. The scheduler is free to ignore this hint.

提示調度程序,當前線程願意放棄當前對處理器的使用。這時,當前線程將會被置爲就緒狀態,和其餘線程同樣等待調度,這時候根據不一樣優先級決定的機率,當前線程徹底有可能再次搶處處理器資源。

3、阻塞狀態(BLOCKED)

阻塞狀態表示線程正等待監視器鎖,而陷入的狀態。

如下場景線程將會阻塞:

  • 線程等待進入synchronized同步方法。
  • 線程等待進入synchronized同步代碼塊。

線程取得鎖,就會從阻塞狀態轉變爲就緒狀態。

4、等待狀態(WAITING)

進入該狀態表示當前線程須要等待其餘線程作出一些的特定的動做(通知或中斷)。

運行->等待

  • 當前線程運行過程當中,其餘線程調用join方法,當前線程將會進入等待狀態。
  • 當前線程對象調用wait()方法。
    -LockSupport.park():出於線程調度的目的禁用當前線程

等待->就緒

  • 等待的線程被其餘線程對象喚醒notify()notifyAll()
  • LockSupport.unpark(Thread),與上面park方法對應,給出許可證,解除等待狀態

5、超時等待狀態(TIMED_WAITING)

區別於WAITING,它能夠在指定的時間自行返回。

運行->超時等待

  • 調用靜態方法,Thread.sleep(long)
  • 線程對象調用wait(long)方法
  • 其餘線程調用指定時間的join(long)
  • LockSupport.parkNanos()
  • LockSupport.parkUntil()

補充:
sleep和yield的不一樣之處:

  • sleep(long)方法會使線程轉入超時等待狀態,時間到了以後纔會轉入就緒狀態。而yield()方法不會將線程轉入等待,而是強制線程進入就緒狀態。
  • 使用sleep(long)方法須要處理異常,而yield()不用。

超時等待->就緒

  • 一樣的,等待的線程被其餘線程對象喚醒,notify()notifyAll()
  • LockSupport.unpark(Thread)

6、消亡狀態

線程的終止,表示線程已經執行完畢。前面已經說了,已經消亡的線程不能經過start再次喚醒。

  • run()和call()線程執行體中順利執行完畢,線程正常終止
  • 線程拋出一個沒有捕獲的Exception或Error。

須要注意的是:主線成和子線程互不影響,子線程並不會由於主線程結束就結束。


許多地方仍需後期補充,敬請期待。

參考資料:《JAVA併發編程實踐》、《瘋狂Java講義》、《Java併發編程藝術》

相關文章
相關標籤/搜索