首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Java 線程生命週期全解析:從創建到終止的狀態流轉

     編輯:Java 程式設計入門

線程的四大核心狀態

正如生命有生老病死,Java 線程也經歷 新建(等待)、運行、阻塞/等待、終止 四種基本狀態。Thread 類提供了豐富的方法來控制這些狀態流轉。

關鍵方法速查表

功能分類方法說明
啟動start()啟動線程,JVM 調用 run()
run()線程執行體,不可直接調用
阻塞/睡眠sleep(long ms)靜態方法,當前線程休眠,釋放 CPU,不釋放鎖
suspend()已棄用,易導致死鎖
resume()已棄用,配合 suspend 使用
join()等待目標線程終止
終止stop()已棄用,強制終止,數據不一致風險
interrupt()中斷線程,拋出 InterruptedException
退出標志推薦方式,通過 volatile boolean 控制循環
狀態檢測isAlive()線程是否存活(啟動後、終止前)
isInterrupted()實例方法,檢測中斷標志
interrupted()靜態方法,檢測當前線程中斷標志並清除

一、創建與運行線程

線程創建後處於「新建」狀態,調用 start() 進入「就緒」隊列,由調度器分配 CPU 進入「運行」狀態執行 run()。

代碼示例:觀察 isAlive 變化

public class LifeCycle extends Thread {
    public void run() {
        int n = 0;
        while ((++n) < 1000); // 模擬耗時操作
    }
    public static void main(String[] args) throws Exception {
        LifeCycle t = new LifeCycle();
        System.out.println("啟動前: " + t.isAlive()); // false
        t.start();
        System.out.println("啟動後: " + t.isAlive()); // true
        t.join(); // 主線程等待
        System.out.println("結束後: " + t.isAlive()); // false
    }
}

二、掛起與喚醒:sleep vs suspend

核心區別:

  • sleep():僅影響當前線程,指定時間後進入就緒態,不釋放鎖
  • suspend()/resume():可跨線程操作,但已棄用,因可能導致死鎖(持有鎖時被掛起)

sleep 使用陷阱

// ❌ 錯誤:試圖在主線程中讓子線程睡眠
thread.sleep(2000); // 實際讓主線程睡眠!

// ✅ 正確:在子線程內部調用
public void run() {
    try { sleep(2000); } catch (InterruptedException e) { ... }
}

注意:sleep 需捕獲 InterruptedException;納秒精度在大多數 JVM 上無法保證。

三、優雅終止線程的三種模式

1. 退出標志(推薦)

public class ThreadFlag extends Thread {
    public volatile boolean exit = false; // volatile 保證可見性
    public void run() { while (!exit); }
    public static void main(String[] args) throws Exception {
        ThreadFlag t = new ThreadFlag();
        t.start();
        Thread.sleep(5000);
        t.exit = true; // 通知線程退出
        t.join();
        System.out.println("線程已優雅退出");
    }
}

2. stop() 強制終止(不推薦)

如同拔掉電源,可能導致數據損壞、鎖未釋放,JDK 標記為 @Deprecated。

3. interrupt() 中斷機制

場景 A:線程處於阻塞態

public void run() {
    try { sleep(50000); } 
    catch (InterruptedException e) { System.out.println(e.getMessage()); } // 輸出: sleep interrupted
}
main() 中調用 thread.interrupt(); // 拋出異常,線程結束

場景 B:輪詢中斷標志

public void run() {
    while (!Thread.interrupted()) { // 或 !isInterrupted()
        // 執行任務
    }
}

最佳實踐總結

  1. 優先使用 volatile boolean 退出標志 或 interrupt() 配合異常處理/標志輪詢
  2. 禁用 stop()、suspend()、resume()
  3. 使用 join() 實現線程協作等待
  4. 正確理解 sleep() 只影響當前線程,不釋放鎖
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved