最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java 線程生命周期與狀態(tài)轉(zhuǎn)換的核心路徑

 更新時(shí)間:2026年01月27日 14:20:01   作者:C雨后彩虹  
本文詳細(xì)講解了Java線程的6種狀態(tài),通過(guò)4個(gè)代碼案例演示了狀態(tài)轉(zhuǎn)換的核心路徑,并介紹了使用 jstack 命令分析線程狀態(tài)的實(shí)戰(zhàn)方法,理解線程的生命周期和狀態(tài)轉(zhuǎn)換,是后續(xù)學(xué)習(xí)線程同步、線程通信的基礎(chǔ),感興趣的朋友跟隨小編一起看看吧

一、前言

在上一篇文章中,我們學(xué)習(xí)了 Java 中創(chuàng)建線程的 5 種方式,掌握了線程的基礎(chǔ)創(chuàng)建與啟動(dòng)邏輯。但線程從創(chuàng)建到銷毀并非一成不變,而是會(huì)在不同狀態(tài)之間轉(zhuǎn)換。理解線程的生命周期和狀態(tài)轉(zhuǎn)換,是解決多線程并發(fā)問(wèn)題的關(guān)鍵。

本文將從理論到實(shí)踐,深入解析 Java 線程的 6 種狀態(tài),演示狀態(tài)轉(zhuǎn)換的核心路徑,并通過(guò)工具分析線程狀態(tài),幫助大家徹底掌握這一核心知識(shí)點(diǎn)。

二、Java 線程的 6 種狀態(tài)

Java 線程的狀態(tài)被明確枚舉在 Thread.State 中,共包含 6 種狀態(tài) ,任何時(shí)刻一個(gè)線程只能處于其中一種狀態(tài)。

狀態(tài)名稱

核心含義

進(jìn)入條件

退出條件

NEW

(新建)

線程對(duì)象已創(chuàng)建,但未調(diào)用start()方法

創(chuàng)建 Thread 實(shí)例后,未執(zhí)行 start()

調(diào)用 start() 方法

RUNNABLE

(可運(yùn)行)

線程正在 CPU 上執(zhí)行,或處于就緒狀態(tài)等待 CPU 調(diào)度

調(diào)用 start() 方法;從其他阻塞 / 等待狀態(tài)喚醒

線程執(zhí)行完畢;進(jìn)入阻塞 / 等待狀態(tài)

BLOCKED

(阻塞)

線程因競(jìng)爭(zhēng)鎖失敗而被阻塞

線程嘗試進(jìn)入 synchronized 代碼塊 / 方法,但鎖被其他線程持有

成功獲取到鎖

WAITING

(等待)

線程無(wú)時(shí)間限制等待,需其他線程主動(dòng)喚醒

調(diào)用 Object.wait()(無(wú)參)、Thread.join()(無(wú)參)、LockSupport.park()

其他線程調(diào)用 Object.notify()/notifyAll()、被 join 的線程執(zhí)行完畢、調(diào)用 LockSupport.unpark()

TIMED_WAITING

(超時(shí)等待)

線程有時(shí)間限制等待,超時(shí)后自動(dòng)喚醒

調(diào)用 Thread.sleep(long)、Object.wait(long)、Thread.join(long)、LockSupport.parkNanos()/parkUntil()

超時(shí)自動(dòng)喚醒;其他線程提前喚醒

TERMINATED

(終止)

線程執(zhí)行完畢或異常退出

run() 方法執(zhí)行完成;線程執(zhí)行過(guò)程中拋出未捕獲異常

無(wú)(線程生命周期結(jié)束)

三、線程狀態(tài)轉(zhuǎn)換流程圖

四、線程狀態(tài)轉(zhuǎn)換

線程狀態(tài)轉(zhuǎn)換有固定的核心路徑,我們通過(guò)代碼案例逐一演示關(guān)鍵轉(zhuǎn)換場(chǎng)景,直觀觀察狀態(tài)變化。

前置說(shuō)明

  • 所有案例中,使用 Thread.getState() 方法獲取線程當(dāng)前狀態(tài)。
  • 為了精準(zhǔn)觀察狀態(tài),使用 Thread.sleep() 控制線程執(zhí)行節(jié)奏,避免因 CPU 調(diào)度過(guò)快導(dǎo)致狀態(tài)無(wú)法捕捉。

場(chǎng)景 1:NEW → RUNNABLE → TERMINATED(基礎(chǔ)路徑)

核心邏輯 :線程創(chuàng)建后處于 NEW 狀態(tài),調(diào)用 start() 進(jìn)入 RUNNABLE ,執(zhí)行完 run() 后進(jìn)入 TERMINATED 。

public class ThreadStateDemo1 {
    public static void main(String[] args) throws InterruptedException {
        // 1. 創(chuàng)建線程,此時(shí)狀態(tài)為 NEW
        Thread thread = new Thread(() -> {
            System.out.println("線程執(zhí)行中,當(dāng)前狀態(tài):" + Thread.currentThread().getState());
            // 模擬任務(wù)執(zhí)行
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "基礎(chǔ)狀態(tài)線程");
        System.out.println("調(diào)用start()前,線程狀態(tài):" + thread.getState()); // NEW
        // 2. 啟動(dòng)線程,進(jìn)入 RUNNABLE 狀態(tài)
        thread.start();
        Thread.sleep(50); // 等待線程進(jìn)入執(zhí)行狀態(tài)
        System.out.println("線程執(zhí)行中,主線程觀察到的狀態(tài):" + thread.getState()); // RUNNABLE
        // 3. 等待線程執(zhí)行完畢
        thread.join();
        System.out.println("線程執(zhí)行完畢,當(dāng)前狀態(tài):" + thread.getState()); // TERMINATED
    }
}

運(yùn)行結(jié)果

調(diào)用start()前,線程狀態(tài):NEW
線程執(zhí)行中,當(dāng)前狀態(tài):RUNNABLE
線程執(zhí)行中,主線程觀察到的狀態(tài):RUNNABLE
線程執(zhí)行完畢,當(dāng)前狀態(tài):TERMINATED

場(chǎng)景 2:RUNNABLE → BLOCKED → RUNNABLE(鎖競(jìng)爭(zhēng)導(dǎo)致阻塞)

核心邏輯 :線程嘗試獲取 synchronized 鎖失敗時(shí),進(jìn)入 BLOCKED 狀態(tài);成功獲取鎖后,回到 RUNNABLE 。

public class ThreadStateDemo2 {
    // 定義一個(gè)鎖對(duì)象
    private static final Object LOCK = new Object();
    public static void main(String[] args) throws InterruptedException {
        // 線程1:先獲取鎖,持有鎖1秒
        Thread thread1 = new Thread(() -> {
            synchronized (LOCK) {
                try {
                    System.out.println(Thread.currentThread().getName() + " 獲取到鎖,狀態(tài):RUNNABLE");
                    Thread.sleep(1000); // 持有鎖,讓線程2阻塞
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "線程1");
        // 線程2:后獲取鎖,會(huì)進(jìn)入 BLOCKED 狀態(tài)
        Thread thread2 = new Thread(() -> {
            synchronized (LOCK) {
                System.out.println(Thread.currentThread().getName() + " 成功獲取鎖,狀態(tài)回到 RUNNABLE");
            }
        }, "線程2");
        // 啟動(dòng)線程1和線程2
        thread1.start();
        Thread.sleep(100); // 確保線程1先獲取鎖
        thread2.start();
        // 觀察線程2的狀態(tài)
        Thread.sleep(200);
        System.out.println(thread2.getName() + " 等待鎖,狀態(tài):" + thread2.getState()); // BLOCKED
        // 等待線程1執(zhí)行完畢,線程2獲取鎖
        thread1.join();
        Thread.sleep(200);
        System.out.println(thread2.getName() + " 執(zhí)行中,狀態(tài):" + thread2.getState()); // RUNNABLE
    }
}

運(yùn)行結(jié)果

線程1 獲取到鎖,狀態(tài):RUNNABLE
線程2 等待鎖,狀態(tài):BLOCKED
線程2 成功獲取鎖,狀態(tài)回到 RUNNABLE
線程2 執(zhí)行中,狀態(tài):RUNNABLE

場(chǎng)景 3:RUNNABLE → WAITING → RUNNABLE(無(wú)參 wait () 喚醒)

核心邏輯 :線程調(diào)用 Object.wait() (無(wú)參)后,釋放鎖并進(jìn)入 WAITING 狀態(tài);需其他線程調(diào)用 notify() / notifyAll() 喚醒,重新競(jìng)爭(zhēng)鎖后回到 RUNNABLE 。

public class ThreadStateDemo3 {
    private static final Object LOCK = new Object();
    private static Thread waitThread; // 等待線程
    public static void main(String[] args) throws InterruptedException {
        // 等待線程:調(diào)用wait()進(jìn)入WAITING狀態(tài)
        waitThread = new Thread(() -> {
            synchronized (LOCK) {
                try {
                    System.out.println(Thread.currentThread().getName() + " 調(diào)用wait(),進(jìn)入WAITING狀態(tài)");
                    LOCK.wait(); // 無(wú)參wait,釋放鎖
                    System.out.println(Thread.currentThread().getName() + " 被喚醒,狀態(tài)回到RUNNABLE");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "等待線程");
        // 喚醒線程:調(diào)用notify()喚醒等待線程
        Thread notifyThread = new Thread(() -> {
            synchronized (LOCK) {
                System.out.println(Thread.currentThread().getName() + " 獲取鎖,準(zhǔn)備喚醒等待線程");
                LOCK.notify(); // 喚醒等待線程
                try {
                    Thread.sleep(500); // 持有鎖,讓等待線程先處于WAITING→BLOCKED
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "喚醒線程");
        waitThread.start();
        Thread.sleep(200);
        System.out.println(waitThread.getName() + " 當(dāng)前狀態(tài):" + waitThread.getState()); // WAITING
        notifyThread.start();
        notifyThread.join();
        Thread.sleep(200);
        System.out.println(waitThread.getName() + " 最終狀態(tài):" + waitThread.getState()); // RUNNABLE/TERMINATED
    }
}

運(yùn)行結(jié)果

等待線程 調(diào)用wait(),進(jìn)入WAITING狀態(tài)
等待線程 當(dāng)前狀態(tài):WAITING
喚醒線程 獲取鎖,準(zhǔn)備喚醒等待線程
等待線程 被喚醒,狀態(tài)回到RUNNABLE
等待線程 最終狀態(tài):TERMINATED

場(chǎng)景 4:RUNNABLE → TIMED_WAITING → RUNNABLE(sleep () 超時(shí)喚醒)

核心邏輯 :線程調(diào)用 Thread.sleep(long) 后,進(jìn)入 TIMED_WAITING 狀態(tài);超時(shí)后自動(dòng)喚醒,回到 RUNNABLE 狀態(tài)( sleep () 不會(huì)釋放鎖 )。

public class ThreadStateDemo4 {
    public static void main(String[] args) throws InterruptedException {
        Thread sleepThread = new Thread(() -> {
            try {
                System.out.println(Thread.currentThread().getName() + " 調(diào)用sleep(1000),進(jìn)入TIMED_WAITING狀態(tài)");
                Thread.sleep(1000); // 超時(shí)等待1秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " 超時(shí)喚醒,狀態(tài)回到RUNNABLE");
        }, "睡眠線程");
        sleepThread.start();
        Thread.sleep(200);
        System.out.println(sleepThread.getName() + " 當(dāng)前狀態(tài):" + sleepThread.getState()); // TIMED_WAITING
        sleepThread.join();
        System.out.println(sleepThread.getName() + " 執(zhí)行完畢,狀態(tài):" + sleepThread.getState()); // TERMINATED
    }
}

運(yùn)行結(jié)果

睡眠線程 調(diào)用sleep(1000),進(jìn)入TIMED_WAITING狀態(tài)
睡眠線程 當(dāng)前狀態(tài):TIMED_WAITING
睡眠線程 超時(shí)喚醒,狀態(tài)回到RUNNABLE
睡眠線程 執(zhí)行完畢,狀態(tài):TERMINATED

五、使用 jstack 命令分析線程狀態(tài)

在實(shí)際開發(fā)中,我們無(wú)法通過(guò)代碼實(shí)時(shí)觀察線上線程的狀態(tài),此時(shí)可以使用 JDK 自帶的 jstack 命令,查看線程的狀態(tài)和調(diào)用棧,定位線程阻塞、死鎖等問(wèn)題。

1、操作步驟

1. 獲取進(jìn)程 ID:使用 jps 命令,查看 Java 進(jìn)程的 PID。

jps
# 輸出示例:1234 ThreadStateDemo2 (1234為PID)

2. 導(dǎo)出線程快照:使用 jstack PID > thread_dump.txt 命令,將線程快照導(dǎo)出到文件。

jstack 1234 > thread_dump.txt

3. 分析線程狀態(tài):打開 thread_dump.txt 文件,搜索線程名稱,查看線程狀態(tài)。

2、實(shí)戰(zhàn)案例(分析 BLOCKED 狀態(tài)線程)

在 ThreadStateDemo2 運(yùn)行時(shí),導(dǎo)出線程快照,會(huì)看到類似如下內(nèi)容:

"線程2" #13 prio=5 os_prio=31 tid=0x00007f8b1282e000 nid=0x5003 waiting for monitor entry [0x0000700001a6f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at ThreadStateDemo2.lambda$main$1(ThreadStateDemo2.java:18)
        - waiting to lock <0x000000076ab81810> (a java.lang.Object)
        - locked <0x000000076ab81810> (a java.lang.Object)
  • java.lang.Thread.State: BLOCKED (on object monitor):明確線程處于 BLOCKED 狀態(tài)。
  • waiting to lock <0x000000076ab81810>:表示線程正在等待獲取該地址的鎖。

六、常見(jiàn)誤區(qū)辨析

  • RUNNABLE 狀態(tài) ≠ 正在執(zhí)行:RUNNABLE 包含 “就緒” 和 “運(yùn)行中” 兩種情況,只有獲取到 CPU 時(shí)間片的線程才會(huì)真正執(zhí)行。
  • sleep () 和 wait () 的區(qū)別: sleep() 屬于 Thread 類,不會(huì)釋放鎖,超時(shí)自動(dòng)喚醒; wait() 屬于 Object 類,會(huì)釋放鎖,需要其他線程喚醒。
  • BLOCKED 和 WAITING 的區(qū)別: BLOCKED 是因競(jìng)爭(zhēng)鎖阻塞, WAITING 是因調(diào)用 wait() / join() 等方法主動(dòng)等待。

六、總結(jié)

本文詳細(xì)講解了 Java 線程的 6 種狀態(tài),通過(guò) 4 個(gè)代碼案例演示了狀態(tài)轉(zhuǎn)換的核心路徑,并介紹了使用 jstack 命令分析線程狀態(tài)的實(shí)戰(zhàn)方法。理解線程的生命周期和狀態(tài)轉(zhuǎn)換,是后續(xù)學(xué)習(xí)線程同步、線程通信的基礎(chǔ)。

下一篇文章,我們將深入分析并發(fā)編程的三大核心特性(原子性、可見(jiàn)性、有序性),并講解volatile關(guān)鍵字的原理與使用場(chǎng)景。

到此這篇關(guān)于Java 線程生命周期與狀態(tài)轉(zhuǎn)換的文章就介紹到這了,更多相關(guān)java線程生命周期內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java中實(shí)現(xiàn)代碼優(yōu)化的技巧分享

    Java中實(shí)現(xiàn)代碼優(yōu)化的技巧分享

    這篇文章主要跟大家談?wù)剝?yōu)化這個(gè)話題,那么我們一起聊聊Java中如何實(shí)現(xiàn)代碼優(yōu)化這個(gè)問(wèn)題,小編這里有幾個(gè)實(shí)用的小技巧分享給大家,需要的可以參考一下
    2022-08-08
  • mybatisplus where QueryWrapper加括號(hào)嵌套查詢方式

    mybatisplus where QueryWrapper加括號(hào)嵌套查詢方式

    這篇文章主要介紹了mybatisplus where QueryWrapper加括號(hào)嵌套查詢方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。
    2022-01-01
  • Java使用ByteBuffer進(jìn)行多文件合并和拆分的代碼實(shí)現(xiàn)

    Java使用ByteBuffer進(jìn)行多文件合并和拆分的代碼實(shí)現(xiàn)

    因?yàn)轵?yàn)證證書的需要,需要把證書文件和公鑰給到客戶,考慮到多個(gè)文件交互的不便性,所以決定將2個(gè)文件合并成一個(gè)文件交互給客戶,但是由于是加密文件,采用字符串形式合并后,拆分后文件不可用,本文給大家介紹了Java使用ByteBuffer進(jìn)行多文件合并和拆分,需要的朋友可以參考下
    2024-09-09
  • Java通過(guò)在主循環(huán)中判斷Boolean來(lái)停止線程的方法示例

    Java通過(guò)在主循環(huán)中判斷Boolean來(lái)停止線程的方法示例

    這篇文章主要介紹了Java通過(guò)在主循環(huán)中判斷Boolean來(lái)停止線程的方法,結(jié)合具體實(shí)例形式分析了java針對(duì)線程的判斷與停止操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2017-04-04
  • PowerJob的ProcessorLoader工作流程源碼解讀

    PowerJob的ProcessorLoader工作流程源碼解讀

    這篇文章主要為大家介紹了PowerJob的ProcessorLoader工作流程源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • JavaFx實(shí)現(xiàn)拼圖游戲

    JavaFx實(shí)現(xiàn)拼圖游戲

    這篇文章主要為大家詳細(xì)介紹了JavaFx實(shí)現(xiàn)拼圖游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-09-09
  • JAVA中try-catch結(jié)構(gòu)之異常處理的使用方法

    JAVA中try-catch結(jié)構(gòu)之異常處理的使用方法

    Java編程中一個(gè)非常重要且實(shí)用的概念,可以幫助我們處理代碼運(yùn)行時(shí)發(fā)生的異常情況,下面這篇文章主要給大家介紹了關(guān)于JAVA中try-catch結(jié)構(gòu)之異常處理的使用方法,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-09-09
  • Spring與Mybatis的整合方法有哪些

    Spring與Mybatis的整合方法有哪些

    本文主要給大家介紹Spring與Mybatis的三種常用整合方法,需要用到的整合框架包mybatis-spring.jar,對(duì)spring mybatis整合感興趣的朋友可以參考下本文
    2015-10-10
  • 詳解Mybatis多參數(shù)傳遞入?yún)⑺姆N處理方式

    詳解Mybatis多參數(shù)傳遞入?yún)⑺姆N處理方式

    這篇文章主要介紹了詳解Mybatis多參數(shù)傳遞入?yún)⑺姆N處理方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • Java?map為什么不能遍歷的同時(shí)進(jìn)行增刪操作

    Java?map為什么不能遍歷的同時(shí)進(jìn)行增刪操作

    這篇文章主要介紹了Java?map為什么不能遍歷的同時(shí)進(jìn)行增刪操作,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-07-07

最新評(píng)論

陇川县| 望奎县| 门头沟区| 海城市| 上虞市| 集贤县| 凤凰县| 修武县| 武宁县| 铜鼓县| 阿拉善右旗| 巩义市| 通许县| 托克托县| 车致| 萨嘎县| 错那县| 分宜县| 清河县| 古蔺县| 白山市| 陆川县| 武穴市| 吉木萨尔县| 乐亭县| 南漳县| 九台市| 兴仁县| 突泉县| 安义县| 广安市| 台中市| 奉贤区| 汉寿县| 千阳县| 兴隆县| 滨州市| 韶山市| 自治县| 四子王旗| 湟中县|