正如生命有生老病死,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()。
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():僅影響當前線程,指定時間後進入就緒態,不釋放鎖suspend()/resume():可跨線程操作,但已棄用,因可能導致死鎖(持有鎖時被掛起)// ❌ 錯誤:試圖在主線程中讓子線程睡眠
thread.sleep(2000); // 實際讓主線程睡眠!
// ✅ 正確:在子線程內部調用
public void run() {
try { sleep(2000); } catch (InterruptedException e) { ... }
}
注意:sleep 需捕獲 InterruptedException;納秒精度在大多數 JVM 上無法保證。
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("線程已優雅退出");
}
}
如同拔掉電源,可能導致數據損壞、鎖未釋放,JDK 標記為 @Deprecated。
場景 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()
// 執行任務
}
}
stop()、suspend()、resume()join() 實現線程協作等待sleep() 只影響當前線程,不釋放鎖