天天看點

阿裡一面:聊聊Java中線程的生命周期狀态

面試時,你是否被問過這道題, “聊聊Java中線程的生命周期狀态吧!”

這幾乎是一道面試必答題,這道題怎麼答才是最佳答案呢?本文就帶大家 來 破解一下! ( 文末有技術書免費送~ )

阿裡一面:聊聊Java中線程的生命周期狀态
一張圖說明線程生命周期

JVM源碼中将線程的生命周期分為建立(New)、可運作(Runnable)、阻塞(Blocked)、等待(Waiting)、逾時等待(Timed_Waiting)和終止(Terminated)這6種狀态。

在系統運作過程中不斷有新的線程被建立,老的線程在執行完畢後被清理,線程在排隊擷取共享資源或者鎖時将被阻塞,是以運作中的線程會在可運作、阻塞、等待狀态之間來回切換。

線程的具體狀态轉化流程如圖所示。

阿裡一面:聊聊Java中線程的生命周期狀态

線程生命周期狀态轉化流程

(1) 調用new方法建立一個線程,這時線程處于建立狀态。

(2) 調用start方法啟動一個線程,這時線程處于可運作狀态。可運作狀态中又分:就緒(Ready)和運作中(Running)兩種狀态。處于就緒狀态的線程等待線程擷取CPU資源,在等待其擷取CPU資源後線程會執行run方法進入運作中狀态;正在運作的線程在調用了yield方法或失去處理器資源時,會再次進入就緒狀态。

(3) 正在運作中的線程在執行了sleep方法、I/O阻塞、等待同步鎖、等待通知、調用suspend方法等操作後,會挂起并進入阻塞狀态。阻塞狀态的線程由于出現sleep時間已到、I/O方法傳回、獲得同步鎖、收到通知、調用resume方法等情況,會再次進入可運作狀态中的就緒狀态,等待CPU時間片的輪詢。該線程在擷取CPU資源後,會再次進入運作狀态。

(4)當線程調用了Object.wait ()、Object.join()、LockSupport.park()後線程進入等待狀态。等待狀态的線程調用Object.notify ()、Object. notifyAll()、LockSupport.unpark(Thread)方法後會再次進入可運作狀态。

(5) 當可運作狀态的線程調用Thread.sleep(long)、Object.wait(long)、Thread.join(long)、LockSupport.parkNanos()、LockSupport.parkUntil()時線程會進入逾時等待狀态。當逾時等待的線程出現逾時時間到、等待進入synchronized方法、等待進入synchronized塊或者調用Object.notify ()、Object. notifyAll()、LockSupport.unpark(Thread)時會再次進入可運作狀态。

(6) 處于可運作狀态的線程,在調用run方法或call方法正常執行完成、調用stop方法停止線程或者程式執行錯誤導緻異常退出時,會進入終止狀态。

線程生命周期詳解
  • 建立狀态(New)

在Java中使用new關鍵字建立一個線程,新建立的線程将處于建立狀态。在建立線程時主要是為線程配置設定記憶體并初始化其成員變量的值。

  • 就緒狀态:Runnable

建立的線程對象在調用start方法之後将轉為可運作狀态。運作狀态中又分:就緒(Ready)和運作中(Running)兩種狀态。就緒狀态指的是JVM完成了方法調用棧和程式計數器的建立,等待該線程的排程和運作。

就緒狀态的線程在競争到CPU的使用權并開始執行run方法的線程執行體時,會轉為運作中狀态,處于運作中狀态的線程的主要任務就是執行run方法中的邏輯代碼。

  • 阻塞狀态:Blocked

運作中的線程會主動或被動地放棄 CPU 的使用權并暫停運作,此時該線程将轉為阻塞狀态,直到再次進入可運作狀态,才有機會再次競争到CPU使用權并轉為運作狀态。阻塞狀态分為如下三種。

(1)等待阻塞: 在運作狀态的線程調用o.wait方法時,JVM會把該線程放入等待隊列(Waitting Queue)中,線程轉為阻塞狀态。

(2)同步阻塞: 在運作狀态的線程嘗試擷取正在被其他線程占用的對象同步鎖時,JVM會把該線程放入鎖池(Lock Pool)中,此時線程轉為阻塞狀态。

(3)其他阻塞: 運作狀态的線程在執行Thread.sleep(long ms)、Thread.join()或者發出I/O請求時,JVM會把該線程轉為阻塞狀态。直到sleep()狀态逾時、Thread.join()等待線程終止或逾時,或者I/O處理完畢,線程才重新轉為可運作狀态。

  • 等待狀态:Waiting

當線程調用了Object.wait()、Thread.join()、LockSupport.park()會進入等待狀态。處于等待狀态的線程正在等待另一個線程執行指定的操作。例如,調用Object.wait()的一個線程對象正在等待另一個線程調用該對象的Object.notify()或Object.notifyAll()。調用thread .join()的線程正在等待指定的線程退出。

  • 逾時等待狀态:Timed_Waiting

逾時等待和等待狀态的不同是,逾時等待狀态的線程經過逾時時間後會自動喚醒。當線程調用了Thread.sleep ()、Object.wait(long)、Thread.join(long)、LockSupport.parkNanos()、LockSupport.parkUntil()後線程會進入逾時等待狀态。

  • 線程終止:Terminated

線程在以如下三種方式結束後轉為終止狀态。

繼續閱讀