多線程是 Java 後端開發的核心技能,也是面試高頻考點。本文梳理進程與線程區別、線程創建方式、生命週期狀態、同步機制、死鎖原理及預防策略等核心知識點,並給出標準化回答思路。
run() 方法。缺點:Java 單繼承限制,若已繼承其他類則無法使用。run(),再傳入 Thread 構造器。優點:解耦任務與執行,支援多繼承,推薦使用。Executors.newFixedThreadPool() 等工廠方法獲取 ExecutorService,提交 Runnable/Callable。優點:複用線程、控制併發量、管理生命週期,生產環境首選。| 狀態 | 說明 |
|---|---|
| NEW | 創建未啟動 |
| RUNNABLE | 就緒/運行中(含等待 CPU 時間片) |
| BLOCKED | 等待獲取監視器鎖 |
| WAITING | 無限期等待(Object.wait()、Thread.join()) |
| TIMED_WAITING | 限時等待(sleep、wait(timeout)) |
| TERMINATED | 執行結束 |
註:原文列舉的「睡眠中」「I/O 阻塞」等屬於上述標準狀態的細分場景。
synchronized 修飾方法,鎖對象為 this(實例方法)或 Class 對象(靜態方法),粒度較粗。synchronized(obj) { ... },可指定任意對象為鎖,粒度更細,併發性能更好。JVM 中每個對象關聯一把鎖,synchronized 編譯為 monitorenter/monitorexit 指令。線程嘗試獲取鎖,成功則執行同步代碼,失敗則進入阻塞隊列。鎖計數器支持重入。
兩個或多個線程互相持有對方需要的鎖並請求對方持有的鎖,導致無限等待。四個必要條件(Coffman 條件):互斥、請求與保持、不剝佔、循環等待。
統一規定所有線程按固定順序獲取鎖(如按對象 hashCode 或業務 ID 排序),打破「循環等待」條件。實踐中可封裝 LockUtil.lockAll(locks...) 內部排序後依次加鎖。
掌握線程基礎模型、創建最佳實踐、狀態流轉、同步原理及死鎖處理,是寫出高併發穩定 Java 應用的基石。實際開發中優先使用 java.util.concurrent 套件(ReentrantLock、CountDownLatch、ConcurrentHashMap 等)替代低層級同步。