天天看點

死磕并發之線程的生命周期詳解

文章開始大家思考一個問題,執行了Thread的start方法之後就代表該線程已經開始執行了嗎?相信大家看完文章應該就能找到答案。

一.線程的生命周期大緻分為以下5個階段

1.NEW

2.RUNNABEL

3.RUNNING

4.BLOCKED

5.TERMINATED

接下來讓我們看下這5個階段分别代表什麼。

二.線程的NEW狀态

我們使用new關鍵字建立一個Thread對象時,它隻是Thread對象的一個狀态。指的是線程已經被建立,但是還不允許配置設定CPU執行,這個狀态是程式設計語言特有的,這裡的建立也隻是程式設計語言層面的被建立,在作業系統層面,線程還沒有被真正建立。

三.線程的RUNNABEL狀态

線程對象進入RUNNABEL狀态必須調用start方法,此時作業系統層面的線程才被真正建立,線程可以配置設定CPU執行。

線程一經建立就能立即得到執行嗎?答案是否定的,線程的運作與否要聽令CPU的排程,也就是說它具備執行的資格,但是并沒有真正地執行起來,而是要等待CPU的排程。

回到我們文章開頭的問題,相信大家已經有了答案。

四.線程的RUNNING狀态

一旦CPU通過輪詢或者其他方式從任務可執行隊列選中了線程,那麼此時它才能真正地執行自己的邏輯代碼。需要注意一個處于RUNNING狀态的線程事實上也是RUNNABLE的,但反之不成立。

在該狀态中,線程狀态會發生如下狀态轉換。

1.直接進入TERMINATED狀态,比如直接調用已經過時的stop方法或者判斷某個邏輯辨別。

2.進入BLOCKED狀态,比如調用了sleep,或者wait方法而加入了waitSet中。

3.進行某個阻塞的IO操作,比如因網絡資料的讀寫而進入BLOCKED狀态。

4.擷取某個鎖資源,進而加入到該鎖的阻塞隊列中而進入BLOCKED狀态。

5.由于CPU排程器輪詢使該線程放棄執行,進入RUNNABLE狀态。

6.線程主動調用yield方法,放棄CPU執行權,進入RUNNABEL狀态。

五.線程的BLOCKED狀态。

調用sleep或者wait方法會使線程進入BLOCKED狀态(需要注意的是,sleep方法不會釋放鎖資源,wait會釋放鎖的資源)。

線程在BLOCKED狀态下可切換如下幾種狀态。

1.直接進入TERMINATED狀态,比如直接調用過時stop方法或者意外死亡(JVM Crash)。

2.線程阻塞操作結束,比如讀取了想要的資料位元組接入到RUNNABLE狀态。

3.線程完成率指定時間的休眠,進入到了RUNNABLE狀态。

4.wait中的線程被其他線程notify/notifyAll喚醒,進入RUNNABLE狀态。

5.線程擷取到了某個鎖的資源,進入RUNNABLE狀态。

6.線程在阻塞過程中被打斷,比如其他線程調用了interrupt方法,進入RUNNABLE狀态。

六.線程的TERMINATED狀态。

TERMINATED是一個線程的最終狀态,在該狀态中線程不會切換到其他任何狀态,線程進入TERMINATED意味着該線程的整個生命周期都結束了。

下列這些情況會使線程進入TERMINATED狀态。

1.線程正常運作結束。

2.線程運作出錯意外結束。

3.JVM Crash導緻所有的線程都結束。