日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

图解 Java 线程的生命周期,看完再也不怕面试官问了

發(fā)布時(shí)間:2024/4/13 java 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 图解 Java 线程的生命周期,看完再也不怕面试官问了 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章首發(fā)自個(gè)人微信公眾號(hào): 小哈學(xué)Java

www.exception.site/java-concur…

在 Java 初中級(jí)面試中,關(guān)于線(xiàn)程的生命周期可以說(shuō)是常客了。本文就針對(duì)這個(gè)問(wèn)題,通過(guò)圖文并茂的方式詳細(xì)說(shuō)說(shuō)。

java線(xiàn)程生命周期

結(jié)合上圖,線(xiàn)程的生命周期大致可分為以下五種狀態(tài)

  • NEW - 新建
  • RUNNABLE - 等待被CPU調(diào)度
  • RUNNING - 正在運(yùn)行
  • BLOCKED - 阻塞
  • TERMINATED - 結(jié)束

一、NEW 狀態(tài)

NEW 狀態(tài)表示線(xiàn)程被新建的狀態(tài),我們來(lái)看一段示例代碼:

Thread thread = new Thread(() -> System.out.println("Hello, world !")); 復(fù)制代碼

當(dāng)我們?cè)诖a中 new 一個(gè) Thread 的時(shí)候,就代表著 thread 線(xiàn)程處于 NEW 狀態(tài)了,但是此時(shí)該線(xiàn)程還未被操作系統(tǒng)創(chuàng)建出來(lái),只有當(dāng)我們調(diào)用了 start() 方法之后,該線(xiàn)程才會(huì)被創(chuàng)建出來(lái)。所以準(zhǔn)確來(lái)說(shuō),NEW 狀態(tài)只是線(xiàn)程對(duì)象的狀態(tài)。


NEW 狀態(tài)的線(xiàn)程能發(fā)生哪些狀態(tài)轉(zhuǎn)變?

new狀態(tài)線(xiàn)程能夠發(fā)生的狀態(tài)轉(zhuǎn)換

NEW 狀態(tài)的線(xiàn)程在調(diào)用 start() 方法后,進(jìn)入 RUNNABLE 狀態(tài)。

二、RUNNABLE 狀態(tài)

當(dāng)我們?cè)诖a中顯式的調(diào)用 start() 方法后,JVM 進(jìn)程會(huì)去創(chuàng)建一個(gè)新的線(xiàn)程,而此線(xiàn)程不會(huì)馬上被 CPU 調(diào)度運(yùn)行,進(jìn)入 RUNNING 狀態(tài),這里會(huì)有一個(gè)中間狀態(tài),就是 RUNNABLE 狀態(tài),你可以理解為等待被 CPU 調(diào)度的狀態(tài):

RUNNABLE中間狀態(tài)

如上圖所示,也就是說(shuō)線(xiàn)程會(huì)從 NEW 狀態(tài) -> RUNNABLE 狀態(tài) ,等待 CPU 調(diào)度,再大白話(huà)一點(diǎn),就是說(shuō)這種線(xiàn)程具備被執(zhí)行的資格,但是能否進(jìn)入執(zhí)行階段,還得看 CPU 的臉色說(shuō)話(huà)。


RUNNABLE 狀態(tài)的線(xiàn)程能發(fā)生哪些狀態(tài)轉(zhuǎn)變?

runnable狀態(tài)轉(zhuǎn)換

RUNNABLE 狀態(tài)的線(xiàn)程無(wú)法直接進(jìn)入 BLOCKED 狀態(tài)和 TERMINATED 狀態(tài)的。

很多小伙伴這里可能有疑問(wèn),為啥呢?

只有處在 RUNNING 狀態(tài)的線(xiàn)程,換句話(huà)說(shuō),只有獲得 CPU 調(diào)度執(zhí)行權(quán)的線(xiàn)程才有資格進(jìn)入 BLOCKED 狀態(tài)和 TERMINATED 狀態(tài)

PS: RUNNABLE 狀態(tài)的線(xiàn)程要么能被轉(zhuǎn)換成 RUNNING 狀態(tài),要么被意外終止(如 kill -9 PID)。

三、RUNNING 狀態(tài)

當(dāng) CPU 調(diào)度發(fā)生,并任務(wù)隊(duì)列中選中了某個(gè) RUNNABLE 線(xiàn)程時(shí),該線(xiàn)程會(huì)進(jìn)入 RUNNING 執(zhí)行狀態(tài),并且開(kāi)始調(diào)用 run()方法中邏輯代碼。


RUNNING 狀態(tài)的線(xiàn)程能發(fā)生哪些狀態(tài)轉(zhuǎn)變?

RUNNING狀態(tài)轉(zhuǎn)換

  • 被轉(zhuǎn)換成 TERMINATED 狀態(tài),比如調(diào)用 stop() 方法;
  • 被轉(zhuǎn)換成 BLOCKED 狀態(tài),比如調(diào)用了sleep, wait 方法被加入 waitSet 中;
  • 被轉(zhuǎn)換成 BLOCKED 狀態(tài),如進(jìn)行 IO 阻塞操作,如查詢(xún)數(shù)據(jù)庫(kù)進(jìn)入阻塞狀態(tài);
  • 被轉(zhuǎn)換成 BLOCKED 狀態(tài),比如獲取某個(gè)鎖的釋放,而被加入該鎖的阻塞隊(duì)列中;
  • 該線(xiàn)程的時(shí)間片用完,CPU 再次調(diào)度,進(jìn)入 RUNNABLE 狀態(tài);
  • 線(xiàn)程主動(dòng)調(diào)用 yield 方法,讓出 CPU 資源,進(jìn)入 RUNNABLE 狀態(tài);

四、BLOCKED 狀態(tài)

上小節(jié)中我們已經(jīng)講到了,進(jìn)入 BLOCKED 原因,這里,我們就直接談?wù)?BLOCK 狀態(tài)的線(xiàn)程能夠發(fā)生哪些狀態(tài)改變:

BLOCKED狀態(tài)轉(zhuǎn)換

  • 被轉(zhuǎn)換成 TERMINATED 狀態(tài),比如調(diào)用 stop() 方法,或者是 JVM 意外 Crash;
  • 被轉(zhuǎn)換成 RUNNABLE 狀態(tài),阻塞時(shí)間結(jié)束,比如讀取到了數(shù)據(jù)庫(kù)的數(shù)據(jù)后;
  • 完成了指定時(shí)間的休眠,進(jìn)入到 RUNNABLE 狀態(tài);
  • 正在 wait 中的線(xiàn)程,被其他線(xiàn)程調(diào)用 notify/notifyAll 方法喚醒,進(jìn)入到 RUNNABLE 狀態(tài);
  • 線(xiàn)程獲取到了想要的鎖資源,進(jìn)入 RUNNABLE 狀態(tài);
  • 線(xiàn)程在阻塞狀態(tài)下被打斷,如其他線(xiàn)程調(diào)用了 interrupt 方法,進(jìn)入到 RUNNABLE 狀態(tài);

五、TERMINATED 狀態(tài)

TERMINATED 狀態(tài)是線(xiàn)程的最終狀態(tài),處于此狀態(tài)中的線(xiàn)程不會(huì)切換到以上任何狀態(tài),一旦線(xiàn)程進(jìn)入了 TERMINATED 狀態(tài),就意味著這個(gè)線(xiàn)程生命的終結(jié),沒(méi)有回頭路了。

以下情況下,線(xiàn)程會(huì)進(jìn)入到 TERMINATED 狀態(tài):

  • 線(xiàn)程正常運(yùn)行結(jié)束,生命周期結(jié)束;
  • 線(xiàn)程運(yùn)行過(guò)程中出現(xiàn)意外錯(cuò)誤;
  • JVM 異常結(jié)束,所有的線(xiàn)程生命周期均被結(jié)束。

六、start 方法源碼解析,何時(shí)調(diào)用的 run() 方法?

通過(guò)圖文,我們了解了線(xiàn)程生命周期的五種狀態(tài),接下來(lái),我們來(lái)看看 start 方法源碼,其實(shí)內(nèi)部的源碼非常簡(jiǎn)單,如下圖所示:

start方法內(nèi)部源碼

  • :首先,會(huì)判斷線(xiàn)程的狀態(tài)是否是 NEW 狀態(tài),內(nèi)部對(duì)應(yīng)的狀態(tài)標(biāo)識(shí)是個(gè) 0,也就是說(shuō)如果不等于 0,直接拋線(xiàn)程狀態(tài)異常;
  • :線(xiàn)程在啟動(dòng)后被加入到 ThreadGroup 中;
  • : start0 是最核心的方法了,就是運(yùn)行狀態(tài)為 NEW (內(nèi)部狀態(tài)標(biāo)識(shí)為 0) 的線(xiàn)程;
  • :start0 是個(gè) native 方法,也就是 JNI 方法;

看到這里,你也許會(huì)有個(gè)疑問(wèn),自己重寫(xiě)的 run 方法是什么時(shí)候被調(diào)用的呢?源碼中也沒(méi)看到調(diào)用啊!!

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

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

run 方法是在調(diào)用 JNI 方法 start0() 的時(shí)候被調(diào)用的,被調(diào)用后,我們寫(xiě)的邏輯代碼才得以被執(zhí)行。

一些面試中,面試官也會(huì)經(jīng)常問(wèn)到這個(gè)問(wèn)題:線(xiàn)程的 start 方法和 run 方法有什么區(qū)別?

相信看完上面的源碼分析,小伙伴們一定可以源碼的角度懟回去了!

七、總結(jié)

本文中,小哈通過(guò)圖文的方式解釋了線(xiàn)程的五種狀態(tài),以及各種狀態(tài)能夠被轉(zhuǎn)換的狀態(tài)。最后,我們簡(jiǎn)單看了一下 start()內(nèi)部源碼,知道了 run() 方法何時(shí)被執(zhí)行的。最后,希望看完本文的小伙伴們能有所收獲,下期見(jiàn)!

八、Ref

  • 《Java高并發(fā)編程詳解》

歡迎關(guān)注微信公眾號(hào): 小哈學(xué)Java

小哈學(xué)Java

贈(zèng)送 | 面試&學(xué)習(xí)福利資源

最近在網(wǎng)上發(fā)現(xiàn)一個(gè)不錯(cuò)的 PDF 資源《Java 核心面試知識(shí).pdf》分享給大家,不光是面試,學(xué)習(xí),你都值得擁有!!!

獲取方式: 關(guān)注微信公眾號(hào): 小哈學(xué)Java, 后臺(tái)回復(fù)"資源",既可免費(fèi)無(wú)套路獲取資源鏈接,下面是目錄以及部分截圖:

福利資源截圖

福利資源截圖

福利資源截圖

福利資源截圖

福利資源截圖

福利資源截圖

福利資源截圖

重要的事情說(shuō)兩遍,獲取方式: 關(guān)注微信公眾號(hào): 小哈學(xué)Java, 后臺(tái)回復(fù)"資源",既可免費(fèi)無(wú)套路獲取資源鏈接 !!!

轉(zhuǎn)載于:https://juejin.im/post/5cbd3df6f265da0363454d78

總結(jié)

以上是生活随笔為你收集整理的图解 Java 线程的生命周期,看完再也不怕面试官问了的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。