併發程式設計——Java執行緒的6種狀態及切換

超Code發表於2021-08-08

前言

本次主要分享一下Java執行緒的六種狀態及其轉換。

如果對於執行緒的建立方式不太瞭解,推薦觀看併發程式設計——認識java裡的執行緒

執行緒的狀態及其轉換

作業系統執行緒的五種狀態

  1. 新建(NEW)
  2. 就緒(RUNNABLE)
  3. 執行(RUNNING)
  4. 阻塞(BLOCKED)
  5. 死亡(DEAD)
    注意:BLOCKED狀態,包括三種型別狀態:等待(wait)、睡眠(sleep)、阻塞(申請資源:I\O、物件的鎖);

Java執行緒的六種狀態

  1. 新建(NEW)
  2. 可執行(RUNNABLE)
  3. 阻塞(BLOCKED)
  4. 等待(WAITING)
  5. 超時等待(TIMED_WAITING)
  6. 終止(TERMINATED)
    注意:Java執行緒中的可執行狀態(RUNNABLE)相當於作業系統執行緒狀態中的就緒狀態(RUNNABLE)和執行狀態(RUNNING)

依據來源於Thread中的原始碼中有執行緒狀態的一個列舉類,目前只有六種。

Java執行緒的狀態圖

新建(NEW)

當用new操作符建立一個新執行緒的時候,如new Thread(r),這個執行緒還沒有開始執行。這意味著它的狀態就是新建(NEW)。當一個執行緒處於新建狀態時,程式還沒有開始執行執行緒中的程式碼。

可執行(RUNNABLE)

一旦呼叫start方法,執行緒就處於可執行(RUNNABLE)狀態。一個可執行的執行緒可能正處於執行,也可能沒有執行。要由作業系統為執行緒提供具體的執行時間。(不過Java規範沒有將正在執行作為一個單獨狀態。一個正在執行的執行緒仍然處於可執行狀態。)

理解可執行狀態

一旦一個執行緒開始執行,它不一定始終保持執行。事實上,執行中的執行緒有時需要暫停,讓其他執行緒有機會執行。執行緒排程的細節依賴於作業系統提供的服務。搶佔式排程系統給每一個可執行執行緒一個時間片來執行任務。當時間片用完時,作業系統剝奪該執行緒的執行權,並給另外一個執行緒一個機會來執行。當選擇下一個執行緒時,作業系統會考慮執行緒的優先順序。

現在所有的桌面以及伺服器作業系統都使用搶佔式排程。但是,像手機這樣的小型裝置可能使用協作式排程。在這樣的裝置中,一個執行緒只有在排程yield方法或者被阻塞或等待時才會失去控制權。

在有多個處理器的機器上,每一處理器執行一個執行緒,可以有多個執行緒並行執行。當然,如果執行緒的數目多於處理器數目,排程器還是需要分配時間片。

記住,在任何給定時刻,一個可執行的執行緒可能正在執行也可能沒有執行(正是因為這樣,這個狀態稱為“可執行”,而不是“執行”)。

阻塞(BLOCKED)

一個正在阻塞等待一個監視器鎖(鎖物件)的執行緒處於這一狀態,說白了就是一個執行緒獲取一個內部的物件鎖的時候這個鎖物件被其他執行緒佔用了,那麼這個執行緒就會被阻塞。是一種鎖阻塞。

等待(WAITING)

一個正在無限期等待另一個執行緒執行一個特別的(喚醒)動作的執行緒處於這一狀態,例如我們呼叫Object.wait或者Thread.join這些就會出現這種情況。

超時等待(TIMED_WAITING)

處於這種狀態的執行緒不會被分配CPU執行時間,不過無須無限期等待被其他執行緒顯示地喚醒,在達到一定時間後它們會自動喚醒。一般像我們使用sleep(1000)方法,讓執行緒睡一秒,過一秒之後執行緒就會自動喚醒繼續執行。
帶有超時引數的方法還有很多,計時版的Object.wait,Thread.join、Lock.tryLock以及Condition.await,呼叫這些方法會讓執行緒進入超時等待狀態。
這些後續我會繼續做分享,敬請期待。

終止(TERMINATED)

1、終止狀態為了兩種情況,一種就是我們呼叫run方法,正常執行完畢,執行緒自然終止。
2、因為一個沒有捕獲的異常終止了run方法,使執行緒意外終止。

具體來說,可以呼叫執行緒的stop方法殺死執行緒。該方法丟擲一個ThreadDeath錯誤物件,這會殺死執行緒。不過,stop方法已經被廢除了,不要在你的程式碼中呼叫這個方法。

既然有講到stop方法,那麼下一篇就來分享一下執行緒所提供的一些方法,敬請期待。

感謝諸君的觀看,文中如有紕漏,歡迎在評論區來交流。如果這篇文章幫助到了你,歡迎點贊?關注。

相關文章