執行緒優先級機制
- 範圍:1 (MIN_PRIORITY) ~ 10 (MAX_PRIORITY),預設 5 (NORM_PRIORITY)
- JVM 規範:優先調度高優先級執行緒,同優先級行為未定義 (視 OS 排程器而定)
- OS 映射:Java 10 級 → OS 通常較少等級 (Linux nice -20~19、Windows 32 級但實際分組較粗),多對一映射導致精度喪失
為何優先級不可靠
| 原因 | 說明 |
| OS 排程器主導 | JVM 僅提示,最終由核心決定時間片分配 |
| 優先級反轉 | 低優先級持有鎖阻塞高優先級,需優先級繼承/天花板協議 (Java 無內建) |
| 飢餓風險 | 高優先級佔用 CPU 導致低優先級長期無法執行 (GC、JIT 編譯執行緒通常高優先級) |
| 跨平台差異 | Windows/Linux/Solaris 行為不一,同樣程式碼表現不同 |
| 規範僅建議 | JLS 不強制保證調度順序 |
正確的併發控制手段
- 同步器:
ReentrantLock、Semaphore、CountDownLatch、CyclicBarrier、Phaser 精確協調執行順序
- 併發集合:
BlockingQueue 實現生產者-消費者、背壓控制
- 執行緒池隔離:不同業務使用獨立
ThreadPoolExecutor,資源配額物理隔離
- CPU 親和性:
taskset、cpuset (Linux) 綁定核心,JDK 无直接 API
- yield() 禮讓:
Thread.yield() 暗示 OS 重新排程,**不保證**生效,僅作微調
- CompletableFuture/Reactive Streams:非阻塞組合、背壓傳播,避免執行緒阻塞等待
多核心時代的並發真相
- 多執行緒 ≠ 更快:僅當任務可並行化、CPU 為瓶頸、多核心可用時才提升吞吐
- 計算密集型:線程數 ≈ CPU 核心數,避免上下文切換開銷
- I/O 密集型:線程數 ≫ CPU 核心數 (如 2×核心數),等待期間切換執行其他任務
- Amdahl 定律:串行部分決定加速上限,優化熱點鎖、減少共享狀態
何時適合多執行緒
- 等待緩慢資源:資料庫、網路、檔案 I/O、外部 API
- 非互動式批次處理:報表產生、資料匯入、影像轉碼
- 高併發伺服器:每連接一任務,線程池隔離、快速回應
- 並行演算:Fork/Join、並行流 (
parallelStream())、矩陣運算
避坑指南
- 不要用
Thread.setPriority() 解決同步、公平、即時性問題
- 不要假設高優先級一定先跑完
- 不要在庫產品程式碼大量調用
yield() 或 sleep() 協調邏輯
- 正確關閉執行緒池,避免 JVM 無法退出 (Daemon 執行緒除外)
- 使用
ThreadLocal 時必須 remove(),防記憶體洩漏
結語
執行緒優先級是「粗糙的建議」,而非「精確的控制」。成熟的併發設計依賴同步器、併發集合、執行緒池隔離、非阻塞演算法,在應用層面構建可預測、可驗證、可維護的併發行為。理解底層調度限制,才能避開「優先級陷阱」,寫出真正健壯的多執行緒程式。
- 上一篇文章: Java 基本數據類型與流操作:DataInput/OutputStream 實戰序列化
- 下一篇文章: Java 文本文件操作完全指南:Reader/Writer 體系與最佳實踐
Copyright ©
程式碼之家 All Rights Reserved