每一個線程都有自己的局部變量表,程序計數器,以及生命週期等。本文主要從各種狀態介紹線程的生命週期轉換
通過上圖可知,線程的生命週期答題可以分爲以下5個主要的階段
1、NEW
當我們用關鍵字new一個Thread對象的時候,此時它並不處於執行狀態,因爲沒有調用start方法啓動該線程,那麼線程的狀態爲NEW狀態,準確的說,它只是Thread對象的狀態,因爲在沒有start之前,該線程根本不存在,與用關鍵字new一個普通的java對象沒有任何分別
NEW狀態通過start方法進入RUNNABLE狀態
2、RUNNABLE
線程對象進入RUNNABLE狀態必須調用start方法,那麼此時纔是真正的再JVM中創建了一個線程,線程一經啓動就可以立即得到執行嘛?答案是否定的,線程的運行與否和進程一樣都要聽令與CPU的調度,那麼我們把這個中間狀態稱爲可執行狀態(RUNNABLE),也就是說它具備執行的資格,但是並沒有真正的執行起來而是在等待CPU的調度。
由於存在Running 狀態,所以不會執行進入 BLOCKED狀態和TERMINATED狀態,即使在線程的執行邏輯中調用了wait、sleep或者其他block的IO操作等,也必須先獲得CPU的調度執行權纔可以,嚴格來講,RUNNABLE的線程只能意外終止或者進入RUNNING狀態
3、RUNNING
一旦CPU通過輪詢或者其他方式從任務可執行隊列中選中了線程,那麼此時它才能真正的執行自己的邏輯代碼,需要說明的一點是一個正在RUNNING狀態的線程事實上也是RUNNABLE的,但是反過來則不成立。
在該狀態中,線程的狀態可以發生如下的狀態轉換
(a)直接進入TERMINATED狀態,比如直接調用JDK已經不推薦使用的stop方法或者判斷某個邏輯標識
(b)進入BLOCKED狀態,比如調用了sleep 或者wait方法而加入了waitSet 中。
(c)進行了某個阻塞的操作,比如因網絡數據的讀寫而進入了BLOCKED狀態。
(d)獲得了某個鎖資源,從而加入了該鎖的阻塞隊列從而進入了 BLOCKED狀態。
(e)由於CPU的調度器輪詢而使該線程放棄執行,進入RUNNABLE狀態。
(f)線程主動調用yield方法,放棄CPU執行權,進入RUNNABLE狀態
4、BLOCKED
線程在BLOCKED狀態中,線程的狀態可以發生如下的狀態轉換
(a)直接進入TERMINATED狀態,比如直接調用JDK已經不推薦使用的stop方法或者判斷某個邏輯標識
(b)線程阻塞的操作結束,比如讀取了想要的數據字節進入到RUNNABLE狀態。
(c)線程完成了指定時間的休眠,進入到RUNNABLE狀態。
(d)Wait 中的線程被其它線程notify/notify喚醒,進入RUNNABLE狀態。
(e)線程獲取到了某個鎖資源,進入RUNNABLE狀態。
(f)線程在阻塞過程中被打斷,比如其它線程調用了interrupt方法,進入RUNNABLE狀態
5、TERMINATED
TERMINATED是一個線程的最終狀態,在該狀態中線程將不會再切換到其它任何狀態,線程進入TERMINATED狀態,意味着線程的整個生命週期都結束了,下列這些情況將會使線程進入TERMINATED狀態
(a)線程正常運行結束,結束生命週期
(b)線程運行出錯意外結束
(c)JVM Crash,導致所有的線程都結束