欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java線程狀態(tài)轉(zhuǎn)換的詳細(xì)過程

 更新時間:2025年09月16日 08:37:21   作者:似水流年流不盡思念  
Java線程狀態(tài)轉(zhuǎn)換是Java多線程編程中的關(guān)鍵概念,對于理解和優(yōu)化并發(fā)程序至關(guān)重要,Java線程在其生命周期中經(jīng)歷多種狀態(tài),這些狀態(tài)之間的轉(zhuǎn)換是由線程調(diào)度器根據(jù)特定的策略來決定的,以下是對Java線程狀態(tài)轉(zhuǎn)換的詳細(xì)說明,需要的朋友可以參考下

一、先明確:Java的6種線程狀態(tài)(Thread.State)

這是狀態(tài)轉(zhuǎn)換的“基本單元”,所有轉(zhuǎn)換都圍繞這6種狀態(tài)進(jìn)行:

1.NEW(新建):線程對象已創(chuàng)建(如new Thread()),但未調(diào)用start(),JVM未為其分配操作系統(tǒng)級線程資源。

2.RUNNABLE(可運(yùn)行):調(diào)用start()后進(jìn)入此狀態(tài),對應(yīng)操作系統(tǒng)線程的“就緒”和“運(yùn)行中”——線程要么在等待CPU調(diào)度(就緒),要么正在CPU上執(zhí)行run()方法(運(yùn)行中),JVM層面不區(qū)分這兩個子狀態(tài)。

3.BLOCKED(阻塞):僅因競爭synchronized鎖失敗而暫停,等待鎖釋放(不涉及Lock接口的鎖,Lock鎖競爭會進(jìn)入WAITING/TIMED_WAITING)。

4.WAITING(無限等待):線程主動調(diào)用無參等待方法,釋放CPU和持有的鎖,必須依賴其他線程顯式喚醒(否則永久等待)。

5.TIMED_WAITING(計時等待):線程調(diào)用帶超時參數(shù)的等待方法,釋放資源后僅等待指定時間,超時后自動喚醒,也可被提前喚醒。

6.TERMINATED(終止):線程的run()方法執(zhí)行完畢,或因未捕獲異常崩潰,生命周期徹底結(jié)束。

線程狀態(tài)流程圖

二、完整狀態(tài)轉(zhuǎn)換流程(帶觸發(fā)條件+場景)

線程從創(chuàng)建到終止,會經(jīng)歷以下核心轉(zhuǎn)換路徑,不同路徑對應(yīng)不同業(yè)務(wù)場景:

1. 初始啟動:NEW → RUNNABLE

  • 觸發(fā)操作:調(diào)用線程對象的start()方法(注意:不能重復(fù)調(diào)用,否則拋IllegalThreadStateException)。
  • 底層邏輯:start()會向JVM注冊線程,JVM向操作系統(tǒng)申請創(chuàng)建線程(如Linux的pthread_create),操作系統(tǒng)將線程加入“就緒隊列”,等待CPU調(diào)度。
  • 場景:
  Thread t = new Thread(() -> { /* 任務(wù)邏輯 */ });
  System.out.println(t.getState()); // 輸出 NEW
  t.start();
  System.out.println(t.getState()); // 輸出 RUNNABLE(大概率,因CPU調(diào)度有延遲)

2. 可運(yùn)行態(tài)內(nèi)部切換:RUNNABLE(就緒)↔ RUNNABLE(運(yùn)行中)

觸發(fā)操作:由操作系統(tǒng)的CPU調(diào)度算法控制,JVM不干預(yù)。

  就緒→運(yùn)行中:CPU空閑時,調(diào)度器從就緒隊列選一個線程分配時間片,線程開始執(zhí)行run()方法。
  運(yùn)行中→就緒:線程的CPU時間片用完,或有更高優(yōu)先級線程進(jìn)入就緒隊列,當(dāng)前線程被搶占,回到就緒隊列。

特點(diǎn):此過程是“隱式轉(zhuǎn)換”,無需代碼觸發(fā),開發(fā)者無法通過Thread.State感知(始終顯示為RUNNABLE)。

3. 鎖競爭:RUNNABLE ↔ BLOCKED

僅針對synchronized鎖的競爭,是“被動阻塞”(線程未主動放棄,因鎖被占用而暫停)。

RUNNABLE → BLOCKED:

觸發(fā):線程嘗試進(jìn)入synchronized代碼塊/方法,但鎖已被其他線程持有。

邏輯:線程從CPU調(diào)度隊列退出,進(jìn)入該鎖的“阻塞隊列”,等待鎖釋放。

BLOCKED → RUNNABLE:

觸發(fā):持有synchronized鎖的線程退出同步塊,釋放鎖。

邏輯:JVM從該鎖的阻塞隊列中喚醒一個線程(公平/非公平取決于JVM實(shí)現(xiàn)),線程重新進(jìn)入就緒隊列,等待CPU調(diào)度。

場景:

Object lock = new Object();
Thread t1 = new Thread(() -> {
    synchronized (lock) { /* 持有鎖執(zhí)行10秒 */ }
});
Thread t2 = new Thread(() -> {
    System.out.println(t2.getState()); // 先 RUNNABLE
    synchronized (lock) { /* 競爭鎖失敗 */ } 
    System.out.println(t2.getState()); // 競爭時變?yōu)?BLOCKED
});
t1.start();
Thread.sleep(100); // 確保t1先持有鎖
t2.start();

4. 主動等待(無限):RUNNABLE ↔ WAITING

線程主動調(diào)用無參等待方法,釋放CPU和鎖,必須由其他線程顯式喚醒(否則“卡死”)。

RUNNABLE → WAITING(3種核心觸發(fā)方式):

1.線程持有synchronized鎖時,調(diào)用lock.wait()(必須在同步塊內(nèi),否則拋IllegalMonitorStateException)。

2.調(diào)用另一個線程的thread.join()(無參):等待目標(biāo)線程執(zhí)行完畢,若目標(biāo)線程未結(jié)束,當(dāng)前線程進(jìn)入等待。

3.調(diào)用LockSupport.park()(無參):無需持有鎖,直接暫停,需通過LockSupport.unpark(thread)喚醒。

WAITING → RUNNABLE(對應(yīng)喚醒方式):

1.其他線程調(diào)用lock.notify()/notifyAll()(喚醒后需重新競爭鎖,競爭成功才回到RUNNABLE)。

2.join()的目標(biāo)線程執(zhí)行完畢(自動喚醒)。

3.其他線程調(diào)用LockSupport.unpark(thread)(直接喚醒,無需競爭鎖)。

場景(wait/notify):

Object lock = new Object();
Thread t1 = new Thread(() -> {
    synchronized (lock) {
        System.out.println(t1.getState()); // RUNNABLE
        lock.wait(); // 釋放鎖,進(jìn)入 WAITING
        System.out.println(t1.getState()); // 被喚醒并重新獲鎖后,回到 RUNNABLE
    }
});
Thread t2 = new Thread(() -> {
    synchronized (lock) {
        lock.notify(); // 喚醒t1
    }
});
t1.start();
Thread.sleep(100);
System.out.println(t1.getState()); // 輸出 WAITING
t2.start();

5. 主動等待(計時):RUNNABLE ↔ TIMED_WAITING

線程調(diào)用帶超時參數(shù)的等待方法,釋放資源后等待指定時間,超時后自動喚醒(也可被提前喚醒)。

RUNNABLE → TIMED_WAITING(5種核心觸發(fā)方式):

1.Thread.sleep(long ms):不釋放鎖,僅暫停指定時間(最常用,無需持有鎖)。

2.持有synchronized鎖時,調(diào)用lock.wait(long ms)。

3.調(diào)用thread.join(long ms):等待目標(biāo)線程指定時間,超時后不再等。

4.LockSupport.parkNanos(long nanos)/parkUntil(long deadline):帶超時的暫停。

5.線程池中的線程等待任務(wù)(如ThreadPoolExecutor的awaitTermination(long, TimeUnit))。

TIMED_WAITING → RUNNABLE(2種喚醒方式):

1.等待時間到期(自動喚醒)。

2.被其他線程顯式喚醒(如notify()/unpark(),與WAITING的喚醒邏輯一致)。

場景(sleep):

Thread t = new Thread(() -> {
    System.out.println(t.getState()); // RUNNABLE
    try {
        Thread.sleep(1000); // 進(jìn)入 TIMED_WAITING
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
    System.out.println(t.getState()); // 超時后回到 RUNNABLE
});
t.start();
Thread.sleep(100);
System.out.println(t.getState()); // 輸出 TIMED_WAITING

6. 最終終止:RUNNABLE → TERMINATED

線程生命周期的終點(diǎn),一旦進(jìn)入此狀態(tài),無法再回到其他狀態(tài)。

觸發(fā)條件:

1.線程的run()方法正常執(zhí)行完畢(無異常)。

2.線程在run()方法中拋出未捕獲的異常(如NullPointerException),導(dǎo)致線程崩潰。

3.其他線程調(diào)用thread.stop()(已廢棄,會強(qiáng)制終止線程,可能導(dǎo)致資源泄漏)。

場景:

Thread t = new Thread(() -> {
    // 任務(wù)執(zhí)行1秒后結(jié)束
    try { Thread.sleep(1000); } catch (InterruptedException e) {}
});
t.start();
Thread.sleep(2000); // 等待t執(zhí)行完畢
System.out.println(t.getState()); // 輸出 TERMINATED

三、關(guān)鍵注意點(diǎn)

1.BLOCKED vs WAITING/TIMED_WAITING:

BLOCKED是“被動等鎖”(僅因synchronized鎖競爭),不釋放已持有的鎖;

WAITING/TIMED_WAITING是“主動等待”,會釋放已持有的鎖(sleep()除外,不釋放鎖)。

2.喚醒后的鎖競爭:

由wait()喚醒的線程,必須重新競爭synchronized鎖,競爭成功才會從WAITING/TIMED_WAITING進(jìn)入RUNNABLE,否則會進(jìn)入BLOCKED狀態(tài)。

3.中斷(interrupt())的影響:

若線程處于WAITING/TIMED_WAITING狀態(tài)時被中斷(其他線程調(diào)用thread.interrupt()),會拋出InterruptedException,并清除中斷標(biāo)志,線程從等待狀態(tài)回到RUNNABLE(需處理異常)。

BLOCKED狀態(tài)的線程被中斷,不會拋出異常,僅設(shè)置中斷標(biāo)志,狀態(tài)仍為BLOCKED。

通過以上流程,可清晰理解線程在不同場景下的狀態(tài)變化,以及代碼操作對狀態(tài)的影響。

以上就是Java線程狀態(tài)轉(zhuǎn)換的詳細(xì)過程的詳細(xì)內(nèi)容,更多關(guān)于Java線程狀態(tài)轉(zhuǎn)換的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • SpringBoot使用Filter實(shí)現(xiàn)簽名認(rèn)證鑒權(quán)的示例代碼

    SpringBoot使用Filter實(shí)現(xiàn)簽名認(rèn)證鑒權(quán)的示例代碼

    這篇文章主要介紹了SpringBoot使用Filter實(shí)現(xiàn)簽名認(rèn)證鑒權(quán)的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • Springboot mybais配置多數(shù)據(jù)源過程解析

    Springboot mybais配置多數(shù)據(jù)源過程解析

    這篇文章主要介紹了Springboot+mybais配置多數(shù)據(jù)源過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-03-03
  • Java線程死鎖代碼詳解

    Java線程死鎖代碼詳解

    本篇文章主要介紹了Java線程死鎖代碼詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2021-11-11
  • Java日期操作類常見用法示例

    Java日期操作類常見用法示例

    這篇文章主要介紹了Java日期操作類常見用法,結(jié)合實(shí)例形式分析了java針對日期時間的獲取、轉(zhuǎn)換常見操作技巧,需要的朋友可以參考下
    2019-07-07
  • Spring無法接收List<event>的解決方案

    Spring無法接收List<event>的解決方案

    在日常開發(fā)中,我們常使用 Spring 的 @EventListener 注解來監(jiān)聽事件,但在處理 批量事件 時,卻可能遇到一些“看似合理但無法生效”的監(jiān)聽方式,本文以實(shí)際具體案例為出發(fā)點(diǎn),結(jié)合源碼分析事件派發(fā)邏輯,并給出兩種可行解決方案,需要的朋友可以參考下
    2025-04-04
  • java使用bitmap實(shí)現(xiàn)可回收自增id的示例

    java使用bitmap實(shí)現(xiàn)可回收自增id的示例

    本文主要介紹了java使用bitmap實(shí)現(xiàn)可回收自增id的示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-10-10
  • JAVA多線程搶紅包的實(shí)現(xiàn)示例

    JAVA多線程搶紅包的實(shí)現(xiàn)示例

    這篇文章主要介紹了JAVA多線程搶紅包的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • SpringBoot 整合 JMSTemplate的示例代碼

    SpringBoot 整合 JMSTemplate的示例代碼

    這篇文章主要介紹了SpringBoot 整合 JMSTemplate的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • idea install 時提示jdk的某個jar包的包不存在的問題

    idea install 時提示jdk的某個jar包的包不存在的問題

    這篇文章主要介紹了idea install 時提示jdk的某個jar包的包不存在的問題,本文給大家分享解決方法,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-09-09
  • java 靜態(tài)工廠代替多參構(gòu)造器的適用情況與優(yōu)劣

    java 靜態(tài)工廠代替多參構(gòu)造器的適用情況與優(yōu)劣

    這篇文章主要介紹了java 靜態(tài)工廠代替多參構(gòu)造器的優(yōu)劣,幫助大家更好的理解和使用靜態(tài)工廠方法,感興趣的朋友可以了解下
    2020-12-12

最新評論