線程的生命周期
New
當(dāng)我們使用關(guān)鍵字new 創(chuàng)建一個(gè)線程對(duì)象時(shí),此時(shí)它并不是處于執(zhí)行狀態(tài)嘹叫,因?yàn)椴]有調(diào)用start()啟動(dòng)該線程,這時(shí)只是Thread對(duì)象的的狀態(tài)(New), 也即沒有start之前诈乒, 該線程根本不存在待笑,與我們用new 創(chuàng)建一個(gè)普通對(duì)象沒有什么區(qū)別。
New 狀態(tài)通過start方法進(jìn)入Runnable狀態(tài)
Runnable
調(diào)用了線程對(duì)象的start方法抓谴,線程狀態(tài)此時(shí)進(jìn)入Runnable狀態(tài),此時(shí)才是真正的在JVM中創(chuàng)建了一個(gè)線程寞缝, 這是線程不一定立即得到執(zhí)行癌压,這是由于線程的運(yùn)行與否和進(jìn)程一樣都要聽命于CPU的調(diào)度,這個(gè)中間狀態(tài)就是線程的可執(zhí)行狀態(tài)(Runnable), 這是也就是說線程具備了執(zhí)行的資格荆陆,但是并沒有執(zhí)行滩届,而是在等待CPU的調(diào)度。
注意: 此時(shí)的Runnable狀態(tài)被啼,不會(huì)直接進(jìn)入Blocked或者Terminated狀態(tài)帜消,即使是在線程執(zhí)行邏輯中調(diào)用wait, sleep或者其他block的IO操作等浓体,也必須先獲得CPU的調(diào)度執(zhí)行權(quán)才可以泡挺, 嚴(yán)格來講,Runnable的線程只能意外終止或者進(jìn)入Running狀態(tài)命浴。
Running
一旦CPU通過輪詢或者其他方式從任務(wù)可執(zhí)行隊(duì)列中選中了線程娄猫,此時(shí)才可能真正執(zhí)行自己的邏輯代碼(run方法中的代碼)贱除, 這里需要說明的是一個(gè)正在Running的線程事實(shí)上也是Runnable的, 但是反過來則不成立媳溺。
該狀態(tài)下線程可發(fā)生如下轉(zhuǎn)換:
- 直接進(jìn)入Terminated狀態(tài)月幌,比如調(diào)用JDK已經(jīng)不推薦使用的stop方法或者判斷某個(gè)邏輯標(biāo)識(shí)
- 進(jìn)入Blocked狀態(tài),比如調(diào)用sleep或者wait 方法而進(jìn)入waitSet中
- 進(jìn)行某個(gè)阻塞的IO操作悬蔽,比如因網(wǎng)絡(luò)數(shù)據(jù)的讀寫而進(jìn)入Blocked狀態(tài)
- 獲取某個(gè)鎖資源扯躺,從而加入到該鎖的阻塞隊(duì)列中而進(jìn)入Blocked狀態(tài)
- 由于CPU的調(diào)度器輪詢是該線程放棄執(zhí)行,進(jìn)入Runnable狀態(tài)
- 線程主動(dòng)調(diào)用yield方法蝎困,放棄CPU的執(zhí)行權(quán)录语,進(jìn)入Runnable狀態(tài)
Blocked
- 調(diào)用sleep或者wait 方法而進(jìn)入waitSet中
- 進(jìn)行某個(gè)阻塞的IO操作,比如因網(wǎng)絡(luò)數(shù)據(jù)的讀寫
- 獲取某個(gè)鎖資源难衰,從而加入到該鎖的阻塞隊(duì)列中
線程在該狀態(tài)下可以切換的狀態(tài)如下:
- 直接進(jìn)入Terminated狀態(tài)钦无,比如調(diào)用JDK已經(jīng)不推薦使用的stop方法或者意外死亡(JVM Crash)
- 線程阻塞的操作結(jié)束, 比如讀取到了想要的數(shù)據(jù)進(jìn)入到Runnable狀態(tài)
- 線程完成了指定時(shí)間的休眠盖袭,進(jìn)入到Runnable狀態(tài)
- Wait中的線程被其他線程notify或者notifyAll喚醒失暂, 進(jìn)入Runnable狀態(tài)
- 線程獲取到了某個(gè)鎖資源,進(jìn)入Runnable狀態(tài)
- 線程在阻塞過程中被打斷鳄虱, 比如其他線程調(diào)用了interrupt方法弟塞, 進(jìn)入Runnable狀態(tài)
Terminated
Terminated 狀態(tài)是線程的最終狀態(tài),在該狀態(tài)中線程將不會(huì)切換到其他的任何狀態(tài)拙已, 線程進(jìn)入Terminated狀態(tài)决记,意味著該線程的整個(gè)生命周期都結(jié)束了。
下列情況將會(huì)使線程進(jìn)入Terminated狀態(tài):
- 線程運(yùn)行正常結(jié)束倍踪,結(jié)束生命周期
- 線程運(yùn)行出錯(cuò)意外結(jié)束
- JVM Crash, 導(dǎo)致所有的線程都結(jié)束
參考
Java 高并發(fā)編程詳解 多線程與架構(gòu)設(shè)計(jì) 汪文君 著