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

Java 線程池核心原理與 ThreadPoolExecutor 完整解析 (一)

     編輯:Java 綜合教學

為何使用線程池?

  • 降低資源消耗:重用已建立線程,減少創建/銷毀開銷。
  • 提高響應速度:任務到達即執行,無需等待線程創建。
  • 提高可管理性:統一分配、調優、監控,避免無限制創建導致系統不穩定。

線程池處理任務流程

線程池任務處理流程圖

  1. 判斷核心線程池是否有閒置線程 → 是則創建新線程執行;否則進入步驟 2。
  2. 判斷工作佇列是否已滿 → 未滿則任務入隊;已滿則進入步驟 3。
  3. 判斷最大線程數是否已達上限 → 未達則創建新線程;已達則交給拒絕策略處理。

ThreadPoolExecutor.execute() 四種情況

  1. 運行線程 < corePoolSize → 創建新線程 (需全域鎖)。
  2. 運行線程 ≥ corePoolSize → 任務入 BlockingQueue。
  3. 佇列已滿且線程 < maximumPoolSize → 創建新線程 (需全域鎖)。
  4. 線程數達 maximumPoolSize → 拒絕任務,調用 RejectedExecutionHandler.rejectedExecution()。

ThreadPoolExecutor 執行流程圖

如何創建線程池?

// 固定大小 10 的線程池
new ThreadPoolExecutor(10, 10, 1, TimeUnit.DAYS, new LinkedBlockingQueue<>());

ThreadPoolExecutor 七大參數詳解

參數說明
corePoolSize核心線程數。任務提交時若運行線程少於此值,創建新線程。可用 prestartAllCoreThreads() 預先啟動。
maximumPoolSize最大線程數。佇列滿時若未達此值,創建新線程。若使用無界佇列則此參數無效。
keepAliveTime非核心線程閒置存活時間。任務多且耗時短可調大提高利用率。
TimeUnit時間單位:天/時/分/秒/毫秒/微秒/奈秒。
workQueue任務佇列。常用:ArrayBlockingQueue(有界)、LinkedBlockingQueue(無界、高吞吐)、SynchronousQueue(直接遞交)、PriorityBlockingQueue(優先級)。
ThreadFactory線程創建工廠,可自定義線程名稱、優先級等。
RejectedExecutionHandler拒絕策略。預設 AbortPolicy 拋異常;另有 CallerRunsPolicy、DiscardPolicy、DiscardOldestPolicy。

提交任務:execute() vs submit()

  • execute(Runnable):無返回值,無法判斷執行成功與否。
  • submit(Callable):返回 Future,可透過 get() 獲取結果或捕獲異常;get(timeout) 可設超時。
ExecutorService executor = Executors.newScheduledThreadPool(3);
executor.execute(() -> System.out.print("runnable"));
Future future = executor.submit(() -> "callable");
System.out.print(future.get()); // 阻塞直到完成

CompletionService:異步任務結果收集器

結合 Executor 與 BlockingQueue,誰先完成誰先返回,而非提交順序。

ExecutorService executor = Executors.newFixedThreadPool(11);
BlockingQueue> queue = new LinkedBlockingQueue<>();
CompletionService cs = new ExecutorCompletionService<>(executor, queue);

for (int i = 0; i < 10; i++) {
    cs.submit(() -> { Thread.sleep(new Random().nextInt(10000)); return Thread.currentThread().getName(); });
}
for (int i = 0; i < 10; i++) {
    System.out.println(cs.take().get()); // 取出已完成任務
}
executor.shutdown();
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved