Java 多線程功能強大,但正確使用需深入理解阻塞機制、死鎖風險、線程生命週期管理及架構選型。本文系統梳理核心問題與最佳實踐。
Thread.sleep():釋放 CPU,不釋放鎖,指定時間後可運行。Object.wait():釋放鎖,進入等待集,需 notify()/notifyAll() 喚醒。Thread.join():等待目標線程終止。LockSupport.park():底層阻塞原語,配合 unpark()。suspend()(已棄用)、無超時 wait()、多鎖獲取順序不一致。tryLock(timeout) 替代無限等待。ConcurrentHashMap, LongAdder 等)。建議:優先使用 java.util.concurrent 高級組件(ReentrantLock, CountDownLatch, Semaphore, CompletableFuture),減少手動 wait/notify。
thread.setDaemon(true); // 必須在 start() 前調用
thread.isDaemon(); // 判斷
ThreadGroup 樹狀結構管理線程,根為 system 組。setMaxPriority(), interrupt(), stop()(棄用) 等對組內所有線程生效。activeCount(), enumerate(), getParent() 等。new ThreadGroup("name") 或指定父組。線程創建時指定組,生命周期不可變更。| 場景特徵 | 是否需要多線程 | 替代方案 |
|---|---|---|
| 無並發需求,單一任務序列執行 | ❌ 否 | 單線程循環 |
| 需並發但順序固定(如管道流水線) | ❌ 否 | 單線程循環 + 階段函數 |
| 真正並發 + 亂序執行(獨立任務、IO 等待、CPU 密集並行) | ✅ 是 | 線程池、CompletableFuture、虛擬線程 |
| 高併發 IO(Web 服務器、網關) | ✅ 是 | NIO/Netty、虛擬線程 |
Executors 工廠或自定義 ThreadPoolExecutor,配置核心/最大線程、隊列、拒絕策略、ThreadFactory(命名、守護屬性)。StructuredTaskScope 自動管理子任務生命週期、異常傳播、取消傳播。Thread.ofVirtual(),輕量級、適合高併發 IO,無需池化。CompletableFuture 鏈式組合,避免共享可變狀態。jstack, JFR, Async-profiler 定位死鎖、活鎖、線程飢餓。多線程本質是「以空間(線程棧、上下文切換)換時間(並行吞吐)」。理解阻塞語義、死鎖條件、守護/組機制,並在架構層面決策是否引入並發,才能寫出高效、穩健的並發程序。拥抱 java.util.concurrent 與虛擬線程,讓並發編程回歸業務邏輯本身。