【圖解】透徹Java線程狀態轉換

大家好,我是阿星,好久不見,歡迎來到Java併發編程系列番外篇線程狀態轉換,內容通俗易懂,請放心食用。

線程狀態

先來個開場四連問

  • Java線程狀態有幾個?

  • Java線程狀態是如何轉換?

  • Java線程狀態轉換什麼情況會進入鎖的等待隊列?

  • Java線程狀態轉換什麼情況會進入鎖的同步隊列?

一提到Java線程狀態,不少讀者立馬想到線程狀態轉換圖,但細想,印象又不深刻,只記得有那麼幾個狀態。

再要你說出Java線程狀態是如何轉換的,腦子裏可能就如下圖一樣,已經是一團漿糊了。

別慌,阿星爲了幫讀者大大們理清楚上面的問題,會一步一步的把線程狀態轉換圖給畫出來,讓讀者大大們真正的理解Java線程狀態轉換

首先線程的狀態可以分爲6態或7態,具體狀態如下

6態

  • New:新建狀態
  • Runnable:可運行狀態
  • Terminated:終止狀態
  • Waiting:等待狀態
  • TimedWaiting:超時等待狀態
  • Blocked:阻塞狀態

7態

  • New:新建狀態
  • Ready:就緒狀態
  • Running:運行狀態
  • Terminated:終止狀態
  • Waiting:等待狀態
  • TimedWaiting:超時等待狀態
  • Blocked:阻塞狀態

其實6態與7態差別不大,只不過7態把Runnable可運行狀態,拆解成了Ready就緒狀態與Running運行狀態。

阿星以7態爲例,來逐步講解它們之間是如何轉換的。

新建狀態(New)

我們可以通過實現Runnable接口或繼承Thread聲明一個線程類,new一個實例後,線程就進入了新建狀態。

一個剛誕生的線程,處於新建狀態。

就緒狀態(Ready)

線程對象創建成功後,調用該線程的start()函數,線程進入就緒狀態,該狀態的線程進入可運行線程池中,等待獲取C P U的使用權。

線程表示,我已經準備好了,此時我是就緒狀態,快選我吧~

運行狀態(Running)

此時線程調度程序正在從可運行線程池中選擇一個線程,該線程進入運行狀態。

換句話說,線程獲取到了C P U時間片。

還沒完呢,當線程時間片用完或調用的yield()函數,該線程回到就緒狀態。

作爲一名運氣好的線程,我進入了運行狀態,但是運氣用完了,我還得回到就緒狀態。

終止狀態(Terminated)

線程繼續運行,直到執行結束或執行過程中因異常意外終止都會使線程進入終止狀態。

線程一旦終止,就不能復生,這是不可逆的過程。

線程的人生迎來了終點,可能一帆風順過完一生,也可能英年早逝令人惋惜。

等待狀態(Waiting)

運行狀態的線程執行wait()、join()、LockSupport.park()任意函數,該線程進入等待狀態。

其中wait()join()函數會讓J V M把該線程放入鎖等待隊列。

處於這種狀態的線程不會被分配C P U執行時間,它們要等待被主動喚醒,否則會一直處於等待狀態。

如果我們要喚醒線程怎麼辦呢?

執行LockSupport.unpark(t)函數喚醒指定線程,該線程回到就緒狀態。

而通過notify()、notifyAll()、join線程執行完畢方式,會喚醒鎖等待隊列的線程,出隊的線程回到就緒狀態。

線程的人生迎來了劫難,聽信小人之言,跑去菲律賓做打工,結果被黑工廠扣下,只希望警察叔叔能早日解救我出去。

超時等待狀態(Timed waiting)

超時等待與等待狀態一樣,唯一的區別就是多了超時機制,不會一直等待被其他線程主動喚醒,而是到達指定時間後會自動喚醒

以下函數會觸發進入超時等待狀態

  • wait(long)
  • join(long)
  • LockSupport.parkNanos(long)
  • LockSupport.parkUtil(long)
  • sleep(long)

其中wait(long)、join(long)函數會讓J V M把線程放入鎖等待隊列。

後面的喚醒劇情就和等待狀態如出一轍,就多了超時時間到了,自動喚醒的動作。

從菲律賓回國後的線程,也做起了違法的勾當,最終被警察抓捕,好在只判了5年,熬一熬就可以出來了。

阻塞狀態(Blocked)

運行狀態的線程獲取同步鎖失敗或發出I/O請求,該線程進入阻塞狀態。

如果是獲取同步鎖失敗J V M還會把該線程放入鎖的同步隊列。


同步鎖被釋放時,鎖的同步隊列會出隊所有線程,進入就緒狀態。

I/O處理完畢時,該線程重新回到就緒狀態。

出獄後的線程,後面的人生一直都是磕磕碰碰,就沒順利過,大家要引以爲戒。

小結

相信讀者大大們跟着阿星的思路來,已經掌握了線程狀態的知識,以後面試官問這類問題,也可以吊打一番,最後放一張簡化的線程轉換圖爲本文畫上句號。


關於我

阿星是一個熱愛技術的Java程序猿,公衆號  「程序猿阿星」 定期分享有趣有料的精品原創文章!

非常感謝各位小哥哥小姐姐們能看到這裏,原創不易,文章有幫助可以關注、點個贊、分享與評論,都是支持(莫要白嫖)!

願你我都能奔赴在各自想去的路上,我們下篇文章見。

本文分享自微信公衆號 - Java中文社羣(javacn666)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章