圖解 Java 線程的生命週期,看完不再怕面試官問了

文章首發自我的微信公衆號: 小哈學Javajava

www.exception.site/java-concur…面試

在 Java 初中級面試中,關於線程的生命週期能夠說是常客了。本文就針對這個問題,經過圖文並茂的方式詳細說說。數據庫

java線程生命週期
java線程生命週期

結合上圖,線程的生命週期大體可分爲如下五種狀態編程

  • NEW - 新建
  • RUNNABLE - 等待被CPU調度
  • RUNNING - 正在運行
  • BLOCKED - 阻塞
  • TERMINATED - 結束

1、NEW 狀態

NEW 狀態表示線程被新建的狀態,咱們來看一段示例代碼:微信

Thread thread = new Thread(() -> System.out.println("Hello, world !"));
複製代碼

當咱們在代碼中 new 一個 Thread 的時候,就表明着 thread 線程處於 NEW 狀態了,可是此時該線程還未被操做系統建立出來,只有當咱們調用了 start() 方法以後,該線程纔會被建立出來。因此準確來講,NEW 狀態只是線程對象的狀態。併發


NEW 狀態的線程能發生哪些狀態轉變?高併發

new狀態線程可以發生的狀態轉換
new狀態線程可以發生的狀態轉換

NEW 狀態的線程在調用 start() 方法後,進入 RUNNABLE 狀態。源碼分析

2、RUNNABLE 狀態

當咱們在代碼中顯式的調用 start() 方法後,JVM 進程會去建立一個新的線程,而此線程不會立刻被 CPU 調度運行,進入 RUNNING 狀態,這裏會有一箇中間狀態,就是 RUNNABLE 狀態,你能夠理解爲等待被 CPU 調度的狀態:學習

RUNNABLE中間狀態
RUNNABLE中間狀態

如上圖所示,也就是說線程會從 NEW 狀態 -> RUNNABLE 狀態 ,等待 CPU 調度,再大白話一點,就是說這種線程具有被執行的資格,可是可否進入執行階段,還得看 CPU 的臉色說話。this


RUNNABLE 狀態的線程能發生哪些狀態轉變?

runnable狀態轉換
runnable狀態轉換

RUNNABLE 狀態的線程沒法直接進入 BLOCKED 狀態和 TERMINATED 狀態的。

不少小夥伴這裏可能有疑問,爲啥呢?

只有處在 RUNNING 狀態的線程,換句話說,只有得到 CPU 調度執行權的線程纔有資格進入 BLOCKED 狀態和 TERMINATED 狀態

PS: RUNNABLE 狀態的線程要麼能被轉換成 RUNNING 狀態,要麼被意外終止(如 kill -9 PID)。

3、RUNNING 狀態

當 CPU 調度發生,並任務隊列中選中了某個 RUNNABLE 線程時,該線程會進入 RUNNING 執行狀態,而且開始調用 run()方法中邏輯代碼。


RUNNING 狀態的線程能發生哪些狀態轉變?

RUNNING狀態轉換
RUNNING狀態轉換

  • 被轉換成 TERMINATED 狀態,好比調用 stop() 方法;
  • 被轉換成 BLOCKED 狀態,好比調用了sleep, wait 方法被加入 waitSet 中;
  • 被轉換成 BLOCKED 狀態,如進行 IO 阻塞操做,如查詢數據庫進入阻塞狀態;
  • 被轉換成 BLOCKED 狀態,好比獲取某個鎖的釋放,而被加入該鎖的阻塞隊列中;
  • 該線程的時間片用完,CPU 再次調度,進入 RUNNABLE 狀態;
  • 線程主動調用 yield 方法,讓出 CPU 資源,進入 RUNNABLE 狀態;

4、BLOCKED 狀態

上小節中咱們已經講到了,進入 BLOCKED 緣由,這裏,咱們就直接談談 BLOCK 狀態的線程可以發生哪些狀態改變:

BLOCKED狀態轉換
BLOCKED狀態轉換

  • 被轉換成 TERMINATED 狀態,好比調用 stop() 方法,或者是 JVM 意外 Crash;
  • 被轉換成 RUNNABLE 狀態,阻塞時間結束,好比讀取到了數據庫的數據後;
  • 完成了指定時間的休眠,進入到 RUNNABLE 狀態;
  • 正在 wait 中的線程,被其餘線程調用 notify/notifyAll 方法喚醒,進入到 RUNNABLE 狀態;
  • 線程獲取到了想要的鎖資源,進入 RUNNABLE 狀態;
  • 線程在阻塞狀態下被打斷,如其餘線程調用了 interrupt 方法,進入到 RUNNABLE 狀態;

5、TERMINATED 狀態

TERMINATED 狀態是線程的最終狀態,處於此狀態中的線程不會切換到以上任何狀態,一旦線程進入了 TERMINATED 狀態,就意味着這個線程生命的終結,沒有回頭路了。

如下狀況下,線程會進入到 TERMINATED 狀態:

  • 線程正常運行結束,生命週期結束;
  • 線程運行過程當中出現意外錯誤;
  • JVM 異常結束,全部的線程生命週期均被結束。

6、start 方法源碼解析,什麼時候調用的 run() 方法?

經過圖文,咱們瞭解了線程生命週期的五種狀態,接下來,咱們來看看 start 方法源碼,其實內部的源碼很是簡單,以下圖所示:

start方法內部源碼
start方法內部源碼

  • :首先,會判斷線程的狀態是不是 NEW 狀態,內部對應的狀態標識是個 0,也就是說若是不等於 0,直接拋線程狀態異常;
  • :線程在啓動後被加入到 ThreadGroup 中;
  • : start0 是最核心的方法了,就是運行狀態爲 NEW (內部狀態標識爲 0) 的線程;
  • start0 是個 native 方法,也就是 JNI 方法;

看到這裏,你也許會有個疑問,本身重寫的 run 方法是何時被調用的呢?源碼中也沒看到調用啊!!

Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread.

上面這段截自 JDK 官方文檔,意思是說:

run 方法是在調用 JNI 方法 start0() 的時候被調用的,被調用後,咱們寫的邏輯代碼才得以被執行。

一些面試中,面試官也會常常問到這個問題:線程的 start 方法和 run 方法有什麼區別?

相信看完上面的源碼分析,小夥伴們必定能夠源碼的角度懟回去了!

7、總結

本文中,小哈經過圖文的方式解釋了線程的五種狀態,以及各類狀態可以被轉換的狀態。最後,咱們簡單看了一下 start()內部源碼,知道了 run() 方法什麼時候被執行的。最後,但願看完本文的小夥伴們能有所收穫,下期見!

8、Ref

  • 《Java高併發編程詳解》

歡迎關注微信公衆號: 小哈學Java

小哈學Java
小哈學Java

贈送 | 面試&學習福利資源

最近在網上發現一個不錯的 PDF 資源《Java 核心面試知識.pdf》分享給你們,不光是面試,學習,你都值得擁有!!!

獲取方式: 關注微信公衆號: 小哈學Java, 後臺回覆"資源",既可免費無套路獲取資源連接,下面是目錄以及部分截圖:

福利資源截圖
福利資源截圖

福利資源截圖
福利資源截圖

福利資源截圖
福利資源截圖

福利資源截圖
福利資源截圖

福利資源截圖
福利資源截圖

福利資源截圖
福利資源截圖

福利資源截圖
福利資源截圖

重要的事情說兩遍,獲取方式: 關注微信公衆號: 小哈學Java, 後臺回覆"資源",既可免費無套路獲取資源連接 !!!

相關文章
相關標籤/搜索