首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 理論與實踐:線程池與工作隊列設計精要

     編輯:Java 相關知識

為什麼需要線程池

服務器應用面臨大量短任務。逐請求創建線程開銷巨大(創建/銷毀時間超過業務處理),且無限制創建導致內存耗盡或上下文切換風暴。線程池通過線程複用攤銷創建成本、固定線程數防止資源耗盡、任務排隊實現削峰填谷。

工作隊列模式:正確的線程池實現

「顯而易見」的實現(調用者等待可用線程)會阻塞提交線程,違背異步初衷。正確模式:

  • 固定數量 Worker 線程啟動後常駐
  • 共享 LinkedList<Runnable> 工作隊列
  • execute(Runnable) 入隊並 notify()
  • Worker wait() 取任務執行
public class WorkQueue {
    private final LinkedList<Runnable> queue = new LinkedList<>();
    private final PoolWorker[] threads;
    public WorkQueue(int n) { threads = new PoolWorker[n]; for (int i=0;i<n;i++) threads[i].start(); }
    public synchronized void execute(Runnable r) { queue.addLast(r); notify(); }
    private class PoolWorker extends Thread {
        public void run() {
            Runnable r;
            while (true) {
                synchronized(queue) {
                    while (queue.isEmpty()) { try { queue.wait(); } catch (InterruptedException ignored) {} }
                    r = (Runnable) queue.removeFirst();
                }
                try { r.run(); } catch (RuntimeException e) { /* log */ }
            }
        }
    }
}

為何用 notify() 而非 notifyAll():單消費者模式下 notify() 避免驚群效應,上下文切換更少。前提是所有 Worker 等待同一條件(隊列非空),滿足 notify() 安全使用條件。

四大風險與應對

風險成因對策
死鎖任務同步等待另一排隊任務,池線程全阻塞禁止排隊任務同步等待其他排隊任務
資源耗盡池過大、任務持有稀缺資源(JDBC/Socket)根據 CPU/IO 特性調整池大小,限制併發資源獲取
併發錯誤wait/notify 使用不當丟失通知直接使用成熟庫
線程洩漏任務拋出 RuntimeException/Error 導致 Worker 退出Worker run() 捕獲 Throwable,保證線程存活

池大小調優公式

  • 純計算任務:N_cpu 或 N_cpu + 1
  • 混合 IO 任務:N_cpu * (1 + WT/ST),WT=平均等待時間,ST=平均服務時間
  • 受限於:內存、文件句柄、數據庫連接數、調度器極限

不要重複造輪子

Doug Lea util.concurrent 提供生產級 PooledExecutor,已修復上述所有坑。JSR 166 將其標準化為 java.util.concurrent (JDK 1.5+)。直接使用 ExecutorService / ThreadPoolExecutor,專注業務邏輯。

最佳實踐清單

  1. 任務不可同步等待其他排隊任務
  2. 長耗時 IO 設置超時並失敗重試
  3. 區分 CPU 密集/IO 密集任務,分池隔離
  4. 監控隊列長度、拒絕策略、線程存活
  5. 優先用 JDK 內建 Executors 工廠或 ThreadPoolExecutor 精細控制
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved