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

J2SE 5.0 並發編程核心:線程池 (Thread Pool) 完整架構與實戰指南

     編輯:Java 相關知識

J2SE 5.0 (java.util.concurrent) 引入工業級線程池框架,徹底改變 Java 多線程開發模式。本文深度解析 ThreadPoolExecutor 核心架構、兩大關鍵概念、任務提交與執行流程、關閉機制,並提供最佳實踐建議。

為什麼需要線程池?三大核心理由

  1. 效能提升:線程建立/銷毀系統開銷大,池化重用避免頻繁上下文切換與記憶體分配。
  2. 關注點分離:業務邏輯 (Task) 與線程生命週期管理解耦。開發者只提交 Runnable/Callable,池負責排程、佇列、線程回收。
  3. 資源可控與穩定性:限制同時活動線程數,防止 OOM、CPU 競爭過度,實現優雅降級 (拒絕策略)。

核心架構:Executor 體系

java.util.concurrent.Executor (介面)
    ▲
    │
java.util.concurrent.ExecutorService (介面)  // 生命週期管理:shutdown, submit, invokeAll...
    ▲
    │
java.util.concurrent.ThreadPoolExecutor (實作類)  // 核心實作,高度可配置

ThreadPoolExecutor 七大建構參數

public ThreadPoolExecutor(
    int corePoolSize,           // 核心線程數 (常駐)
    int maximumPoolSize,        // 最大線程數 (峰值)
    long keepAliveTime,         // 非核心線程閒置存活時間
    TimeUnit unit,              // 時間單位
    BlockingQueue workQueue, // 任務佇列
    ThreadFactory threadFactory,       // 線程工廠 (命名、優先權、daemon)
    RejectedExecutionHandler handler   // 拒絕策略 (佇列滿 + 線程達最大)
)

兩大關鍵動態概念:Sizes 與 Queues

線程池大小動態調整

  • corePoolSize:最小常駐線程數。啟動時不建立,首次任務到達才創建 (除非 prestartAllCoreThreads())。
  • maximumPoolSize:上限。當佇列滿且線程數 < maximum 時創建新線程。
  • getPoolSize():當前實際線程數。

任務佇列策略

  • 無界佇列 (如 LinkedBlockingQueue):任務無限堆積,maximumPoolSize 失效,僅 corePoolSize 生效。
  • 有界佇列 (如 ArrayBlockingQueue(100)):佇列滿則嘗試擴充線程至 maximumPoolSize,仍滿則觸發拒絕策略。
  • 同步移交佇列 (SynchronousQueue):不儲存任務,直接移交給線程。無閒置線程則創建新線程 (至 maximum),否則拒絕。適合高吞吐、任務輕量場景。

任務提交與執行完整決策流程

呼叫 execute(task) 時,依序判斷:

  1. 線程數 < corePoolSize → 立即創建新線程 執行 (即使有閒置線程)。
  2. core ≤ 線程數 < maximum 且 有閒置線程 → 閒置線程執行。
  3. core ≤ 線程數 < maximum 且 無閒置線程 → 嘗試入佇列 (不阻塞)。成功則等待;失敗 (佇列滿) → 創建新線程 執行。
  4. 線程數 = maximum 且 無閒置線程 → 嘗試入佇列。成功等待;失敗 → 觸發 RejectedExecutionHandler。

任務完成後的線程回收邏輯

  • 線程數 > corePoolSize:線程等待新任務,超時 (keepAliveTime) 後 退出縮減。若 keepAliveTime=0,任務完成即退出 (忽略 core)。
  • 線程數 ≤ corePoolSize:線程 無限期阻塞等待 新任務 (除非 timeout=0)。

關閉機制:優雅停機 vs 立即停機

實戰最佳實踐

  1. 使用 Executors 工廠方法快速開始:
    ExecutorService fixed = Executors.newFixedThreadPool(10);          // core=max=10, 無界佇列
    ExecutorService cached = Executors.newCachedThreadPool();          // core=0, max=Integer.MAX, SynchronousQueue
    ExecutorService single = Executors.newSingleThreadExecutor();      // 序列化執行
    ExecutorService scheduled = Executors.newScheduledThreadPool(5);   // 定時/週期任務
  2. 生產環境建議自訂 ThreadPoolExecutor:明確命名線程 (ThreadFactoryBuilder)、有界佇列防 OOM、自訂拒絕策略 (記錄日誌、持久化、降級處理)。
  3. 任務設計:實作 Runnable (無回傳) 或 Callable (有回傳/拋出異常),避免長時間阻塞 I/O 佔用核心線程 (考慮分離 I/O 池)。
  4. 監控指標:getActiveCount()、getQueue().size()、getCompletedTaskCount()、getRejectedExecutionHandler() 統計。

完整範例:自訂線程池與優雅關閉

public class ThreadPoolDemo {
    public static void main(String[] args) throws InterruptedException {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
            5, 10, 60L, TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(100),
            new ThreadFactoryBuilder().setNameFormat("OrderProcessor-%d").build(),
            new ThreadPoolExecutor.AbortPolicy() // 或自訂 RejectedExecutionHandler
        );

        // 提交 100 個任務
        for (int i = 0; i < 100; i++) {
            final int taskId = i;
            executor.execute(() -> {
                System.out.printf("[%s] Processing task %d%n", Thread.currentThread().getName(), taskId);
                try { Thread.sleep(100); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
            });
        }

        // 優雅關閉
        executor.shutdown();
        if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
            System.err.println("Timeout, forcing shutdown...");
            executor.shutdownNow();
        }
        System.out.println("All tasks completed.");
    }
}

總結

J2SE 5.0 線程池框架將「線程管理」從業務代碼中抽離,提供工業級的可配置性、穩定性與監控能力。掌握 core/maximum、佇列類型、拒絕策略、關閉流程四大核心維度,是編寫高併發 Java 應用的必備技能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
方法行為回傳值
shutdown()停止接受新任務,處理完佇列現有任務void
shutdownNow()嘗試中斷執行中任務,返回未處理任務列表List<Runnable>
awaitTermination(timeout, unit)阻塞等待池終止,配合 shutdown 使用boolean