線程狀态
先來個開場四連問
-
-
線程狀态有幾個?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
處理完畢時,該線程重新回到就緒狀态。