掌握執行緒狀態是編寫高併發程式、排查死鎖/飢餓問題的基礎。Java Thread.State 枚舉定義了 6 種狀態,本文結合源碼與實際場景,詳細解析每種狀態的觸發條件、轉換路徑及常見誤區。
| 狀態 | 枚舉常量 | 核心含義 | 典型觸發場景 |
|---|---|---|---|
| 新建 | NEW | 執行緒物件已建立,尚未啟動 | new Thread() |
| 可執行 | RUNNABLE | 在 JVM 中執行中,或等待作業系統排程 CPU | thread.start() 後、佔用 CPU 時、等待 CPU 時 |
| 阻塞 | BLOCKED | 等待監視器鎖(進入 synchronized 區塊/方法) | 嘗試進入已被佔用的 synchronized 區塊 |
| 等待 | WAITING | 無限期等待另一執行緒的特定動作 | Object.wait()、Thread.join()、LockSupport.park() |
| 定時等待 | TIMED_WAITING | 帶超時的等待 | Thread.sleep()、Object.wait(timeout)、Thread.join(timeout)、LockSupport.parkNanos/Until |
| 終止 | TERMINATED | 執行緒已結束執行 | run() 正常返回、拋出未捕獲異常 |
NEW --start()--> RUNNABLE --執行/等待CPU--> RUNNABLE RUNNABLE --synchronized(鎖被佔用)--> BLOCKED --獲取鎖--> RUNNABLE RUNNABLE --wait()/join()/park()--> WAITING --notify()/notifyAll()/interrupt()--> RUNNABLE RUNNABLE --sleep(timeout)/wait(timeout)/join(timeout)/parkNanos/Until--> TIMED_WAITING --超時/通知/中斷--> RUNNABLE RUNNABLE --run()結束/異常--> TERMINATED
synchronized 失敗,鎖釋放自動恢復 不可中斷interrupt() 可打斷並拋出 InterruptedExceptionJVM 將「正在執行」與「就緒等待 CPU」合併為 RUNNABLE,因作業系統排程器對 JVM 不透明,JVM 無法區分執行緒當下是佔用 CPU 還是排隊中。
Thread t = new Thread(() -> { /* ... */ });
System.out.println(t.getState()); // NEW
t.start();
System.out.println(t.getState()); // 通常是 RUNNABLE,極罕見 BLOCKED/WAITING
注意:getState() 僅供監控/除錯,不可用於同步控制(狀態讀取到使用之間可能已變更)。
# 導出執行緒快照
jstack -l <pid> > thread_dump.txt
# 關注重點
# BLOCKED 大量出現 → 鎖爭用嚴重,檢查 synchronized 範圍、考慮 ReentrantLock/分段鎖
# WAITING/TIMED_WAITING 大量 → 線程池空閒、資源池耗盡、外部呼叫慢
# RUNNABLE 但 CPU 低 → 可能在進行 GC、JNI 呼叫、大量系統呼叫
理解 6 大狀態及其轉換,是從「會用多執行緒」進階到「駕馭多執行緒」的必修課。建議配合 jstack、VisualVM、Arthas 等工具,在真實專案中觀察、驗證、內化。