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

Java 原生執行緒池原理與 Guava ListenableFuture 補充

     編輯:Java 綜合教學

Java 原生執行緒池原理與 Guava ListenableFuture 補充

轉眼間兩個月未更新部落格。一方面覺得需學習的技術太多,寫經驗分享不如多讀幾本技術書;另一方面網路上已有大量成熟中文文章,重複造輪子意義不大。既然決定寫,就希望能提供一些不同視角與啟發。

為什麼需要執行緒池?

使用成熟框架開發併發應用,不僅能節省建構專案時間,更能提升應用效能。手動實現的併發應用不僅耗時,效能往往也難以達標。

以曾開發的多執行緒下載器為反例:

  1. 執行緒數由使用者配置:使用者誤以為執行緒越多越快,設定 50 條執行緒下載單一任務,導致 JVM 花費大量資源在上下文切換,效能反而不如單程序。CPU 密集型任務最佳執行緒數為 CPU 核心數 1 倍;I/O 密集型為 1.5~2 倍。不當的執行緒數會導致執行緒抖動、CPU 抖動。
  2. 同步處理 HTTP 接收與解析:HTTP 報文接收等待時間長,解析耗資源少。同步處理會導致下載進程空轉或阻塞。應解耦接收與解析,採用生產者-消費者模式,非同步處理報文。

減少上下文切換的四大策略

  1. 無鎖併發程式設計:資料 ID 取模分段,不同執行緒處理不同段資料
  2. CAS 演算法:Atomic 套件利用 CAS 更新資料,無需加鎖(但執行緒空轉仍存在)
  3. 使用最少執行緒:避免建立不必要的執行緒
  4. 協程:單執行緒實現多任務調度

執行緒池三大效益

  1. 降低資源消耗:重複利用已建立執行緒,減少建立/銷毀開銷
  2. 提高響應速度:任務到達即可執行,無需等待執行緒建立
  3. 提高可管理性:統一分配、調優、監控,避免無限制建立降低系統穩定性

Executor 框架:兩級調度模型

Executor框架兩級調度模型

  • 上層(應用層):將應用分解為任務,由用戶級調度器(Executor 框架)映射為固定數量執行緒
  • 底層(OS 層):作業系統核心將執行緒映射至硬體處理器

這是一種工作單元與執行機制的解耦。HotSpot VM 中 Java 執行緒一對一映射為本地 OS 執行緒。

Fork/Join 框架:遞迴調度模型

為充分利用多核處理器,需提升應用本身並行能力。Fork/Join 將任務遞迴拆分為子任務,執行後合併結果。雖類似 MapReduce,但實際效能遠不如 Executor,遞迴棧超過十層時 JVM 甚至會卡死或崩潰,故不再深究。

Executor 框架核心組件

  1. Executor:介面,將任務提交與執行分離
  2. ThreadPoolExecutor:執行緒池核心,執行被提交任務
  3. Future / FutureTask:代表非同步計算結果
  4. Runnable / Callable:可被 ThreadPoolExecutor 執行的任務類型

四種常見 Executor 實現

1. FixedThreadPool

最常用實現,搭配 Runtime.getRuntime().availableProcessors() 分配處理器核心數的執行緒。內部使用無界 LinkedBlockingQueue,任務可能無限積壓,建議監控 size() 防止隊列無限增長。

2. SingleThreadExecutor

等價於 Executors.newFixedThreadPool(1),保證任務循序執行。

3. CachedThreadPool

使用 SynchronousQueue(無容量隊列),offer 必須對應 poll。工作執行緒飽和時會阻塞,類似 Exchanger 但支援多生產者/消費者。

4. ScheduledThreadPoolExecutor

內部使用 DelayQueue(優先級隊列封裝),時間早的任務優先級高。用於延遲執行或定期執行任務,功能類似 Timer 但更靈活,支援多後台執行緒。

Future 與 Guava ListenableFuture

Future.get() 取回結果可能阻塞,最壞情況下非同步退化為同步。Guava 提供 ListenableFuture,採用觀察者模式,非同步計算完成後立即執行 addListener 指定的 Runnable,實現「完成即通知」。

教學資源:https://ifeve.com/google-guava-listenablefuture/

程式碼範例:SingleThreadExecutor

public class ExecutorDemo {
    public static void main(String[] args) {
        ExecutorService single = Executors.newSingleThreadExecutor();
        Callable<String> callable = Executors.callable(new Runnable() {
            @Override public void run() {
                for (int i = 0; i < 100; i++) {
                    try { System.out.println(i); }
                    catch (Throwable e) { e.printStackTrace(); }
                }
            }
        }, "success");
        Future<String> f = single.submit(callable);
        try {
            System.out.println(f.get());
            single.shutdown();
        } catch (Throwable e) { e.printStackTrace(); }
    }
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved