1. 程式人生 > 實用技巧 >一個 Java 執行緒生命週期,我竟然可以扯半小時

一個 Java 執行緒生命週期,我竟然可以扯半小時

乘風破浪會有時,直掛雲帆濟滄海,高考的同學們加油!

面試官:你不是精通 Java 併發嗎?從基礎的 Java 執行緒生命週期開始講講吧。

好的,面試官。吧啦啦啦...

如果要說 Java 執行緒的生命週期的話,那我覺得就要先說說作業系統的執行緒生命週期

因為 JVM 是跑在作業系統上面的嘛,所以是繞不過去的,而且可以說, Java 語言中的執行緒本質上就是作業系統的執行緒

聰明的你肯定也發現了,不管是作業系統,還是 Java 或者 C# 都有執行緒的概念。在它們之間,關於執行緒的生命週期這一部分,肯定是有相同之處的,否則的話,作業系統自己一套生命週期流程, Java 又有自己的一套, C# 又有自己的一套,而且相互之間還要能夠互相配合,這種成本想想就大的不行對吧

所以咱們就來看看,通用的執行緒生命週期都有啥

可以看到,主要有 new , ready , running , waiting , terminated 5 種狀態

其中:

  • new 只是說,這個執行緒被建立了,但是還不允許分配 CPU 執行。因為這個狀態只是說明你在程式語言層面被建立了,作業系統層面還沒有被建立,肯定就談不上分配 CPU 執行了

  • ready 這個狀態是說,在作業系統層面已經成功建立了,所以接下來就是等待分配 CPU 執行了。還記得那句經典的嘛?ready ?go !

  • running 的狀態,相信你就知道了,我都已經 ready 了,此時如果再給我分配一下 CPU 我是不是就可以 go 了?那不就是 running 狀態了嘛

  • waiting 狀態,就是執行緒在 running 狀態的時候,突然發現,哎,我需要進行一下 I/O 操作,或者需要等待某個事件發生(比如說需要某個條件變數),這個時候是不是就不能再繼續 happy 的 running 了。那咋辦?waiting 一下唄

    • 那你都 waiting 了,佔用的 CPU 資源是不是應該釋放掉?所以說, waiting 狀態的執行緒是永遠沒有機會獲得 CPU 使用權的

    • 你是不是一聽「永遠沒有機會」這幾個字就給嚇壞了,我該不會永遠沒有機會執行了吧。放心吧,你不是在 waiting 嘛,等你 wait 的事件發生了,就可以繼續到 running 狀態

  • 當整個執行緒執行完畢,或者出現異常的時候,就進入了 terminated 狀態,也就是執行緒的使命就完成啦,處於 terminated 狀態的執行緒不會再切換到其他狀態了

通用的執行緒生命週期以及它們之間是如何切換的,到這裡,應該就比較清楚了

接下來咱們看看 Java 執行緒的生命週期,在這個基礎上是怎麼做的優化,有什麼區別

Java 執行緒的生命週期

咱們先來瞅瞅原始碼定義的狀態(為了突出重點,我把註釋都去掉了):

publicenumState{
NEW,
RUNNABLE,
BLOCKED,
WAITING,
TIMED_WAITING,
TERMINATED;
}

能夠清楚的看到,在原始碼中定義了 6 種執行緒狀態,剛才的通用狀態有幾種來著?5 種對吧,現在是 6 種。

這 6 種是幹啥的?剛才的 5 種狀態以及它們之間的切換我搞清楚了,這 6 種狀態它們之間又是怎麼切換的呢?

這 6 個狀態咱們也是分別來看:

  • NEW 到 RUNNABLE ,應該是挺容易理解的,就是 thread 呼叫了 start 方法

    • Java 剛創建出來的 Thread 物件就是 NEW 狀態,建立 Thread 物件主要有兩種方法,一種是繼承 Thread 物件,重寫 run() 方法,一種是實現 Runnable 介面,重寫 run() 方法,並將該實現類作為建立 Thread 物件的引數

    • 但是還記得嘛, NEW 只是說,這個執行緒在程式語言層面建立了,在作業系統層面還沒有建立,那當然就不會被作業系統排程了對不對,就更談不上執行了

    • 所以 Java 執行緒如果想要執行的話,就必須轉換到 RUNNABLE 狀態,也就是 thread 呼叫 start 方法

  • RUNNABLE 與 BLOCKED ,如果執行緒等待 synchronized 的隱式鎖時,就會從 RUNNABLE 狀態轉到 BLOCKED 狀態。因為 synchronized 修飾的方法/程式碼塊同一時刻只允許一個執行緒執行,所以其他執行緒就只能等待了唄,當等待的執行緒獲得 synchronized 隱式鎖時,就會從 BLOCKED 狀態轉到 RUNNABLE 狀態

    • 在這裡有沒有個疑問?就是執行緒在 wait 一個條件發生時,在作業系統層面執行緒會轉到 waiting 狀態,那麼在 JVM 層面呢?在 JVM 層面, Java 執行緒狀態是不會發生變化的。也就是這個時候 Java 執行緒的狀態依然是 RUNNABLE 狀態
  • RUNNABLE 與 WAITING 狀態轉換,我感覺圖已經說得很好了,在這裡不再贅述

  • RUNNABLE 與 TIMED_WAITING 狀態轉換,我感覺圖已經說得很好了,在這裡也不再贅述,仔細觀察下會發現, TIMED_WAITING 與 WAITING 相比,就是多了超時引數,畢竟 TIMED_WAITING 是有時限等待嘛

  • RUNNABLE 到 TERMINATED ,這個過程比較好理解,執行緒執行完 run() 方法之後,就自動到 TERMINATED 狀態了,當然瞭如果在執行 run() 方法過程中有異常丟擲,也會導致執行緒終止

    • 有時候我們可能需要強制中斷 run() 方法的執行,怎麼辦呢?是使用 stop() 方法還是 interrupt() 方法呢?正確的姿勢是呼叫 interrupt() 方法

    • stop() 方法會真的殺死執行緒,不給執行緒一點兒喘息的機會,如果被殺死的執行緒持有 synchronized 隱式鎖,那就再也不會釋放掉這個鎖了,接下來的執行緒也就沒辦法獲得 synchronized 隱式鎖,是不是特別危險?同樣 suspend() 和 resume() 這兩個方法也是不建議使用

    • interrupt() 方法相比於 stop() 方法就溫柔很多,它只是通知執行緒後續的操作可以不用去執行了,執行緒可以選擇執行現在就不執行,當然也可以選擇再執行一段時間後再停止,或者我就不聽你的,非要執行完,都沒關係, interrupt() 只是通知一下你而已。就比如你要做火車去一個地方,突然通知你這個火車晚點了,你可以選擇無視這個通知繼續等待,或者選擇另外一趟高鐵,但是不管你做什麼,和火車站都沒啥關係,它通知的責任盡到了

看到這裡應該就比較清楚了吧

在 Java 執行緒生命週期中, RUNNABLE 狀態是將 ready 和 running 兩種狀態合併在了一起,而 BLOCKED , WAITING , TIMED_WAITING 這三種狀態其實就是 waiting 狀態,也就是執行緒要等待某些事件發生,才能繼續向下執行下去

關於 Java 執行緒的生命週期,到這裡就說完啦

畫個圖 + 講解,和麵試官扯半小時應該沒問題吧?

版權所屬:Java極客技術歸原作者所有

java交流學習資源大全檔案下載地址:https://jq.qq.com/?_wv=1027&k=jx7ERZrp學習手冊,面試題,開發工具,PDF文件書籍教程,練習專案+原始碼

Java自學資料學習交流群:926452303

聲援博主:您的肯定就是我進步的動力。如果你感覺還不錯,就請鼓勵一下吧!記得隨手點波推薦不要忘記哦!!!

別忘了點推薦留下您來過的痕跡