理解線程狀態機是寫好併發程式、排查死鎖/活鎖/飢餓的基石。JDK 定義 6 大狀態(Thread.State 枚舉),轉換觸發條件如下:
new Thread() 創建,未 start()。start() 後,就緒/運行中(OS 調度決定)。synchronized 同步塊/方法,獲取鎖失敗。Object.wait()、Thread.join()、LockSupport.park()。sleep()、wait(timeout)、join(timeout)、parkNanos/parkUntil。run() 正常返回或拋出未捕獲異常結束。| 從狀態 | 觸發動作 | 到狀態 |
|---|---|---|
| NEW | thread.start() | RUNNABLE |
| RUNNABLE | 進入 synchronized 獲取鎖失敗 | BLOCKED |
| RUNNABLE | Object.wait() / Thread.join() / LockSupport.park() | WAITING |
| RUNNABLE | Thread.sleep() / wait(timeout) / join(timeout) / parkNanos() | TIMED_WAITING |
| BLOCKED | 獲得鎖 | RUNNABLE |
| WAITING | Object.notify()/notifyAll() / LockSupport.unpark() / join 線程結束 | RUNNABLE |
| TIMED_WAITING | 超時 / notify / unpark / join 線程結束 | RUNNABLE |
| RUNNABLE/WAITING/TIMED_WAITING/BLOCKED | run() 結束或拋出未捕獲異常 | TERMINATED |
wait() 必須在同步塊內調用),等待外部通知。
jstack / VisualVM 觀察線程狀態分佈,大量 BLOCKED 提示鎖爭用,大量 WAITING 可能是連接池/任務佇列空閒。BLOCKED,各持有對方需求的鎖。TERMINATED 線程數持續增長,或守護線程未正確關閉。將狀態圖貼在工位,併發除錯不再盲目。