多執行緒編程學習十(執行緒池原理).

  • 2019 年 10 月 6 日
  • 筆記

一、執行緒池工作流程

  1. 執行緒池判斷核心執行緒池裡的執行緒是否都在執行任務。如果不是,則創建一個新的工作執行緒來執行任務(需要獲得全局鎖)。如果核心執行緒池裡的執行緒都在執行任務,則進入下個流程。
  2. 執行緒池判斷工作隊列是否已滿。如果工作隊列沒有滿,則將新提交的任務存儲在這個工作隊列里。如果工作隊列滿了,則進入下個流程。
  3. 執行緒池判斷執行緒池的執行緒是否都處於工作狀態。如果沒有,則創建一個新的工作執行緒來執行任務(需要獲得全局鎖)。如果已經滿了,則交給飽和策略(例如拋出異常)來處理這個任務。

tips:這樣的設計方案,可以避免頻繁的執行緒創建,大部分的工作任務都會停留在第二步。

二、Executor 框架

在 Java 中,執行緒池的知識是要從 Executor 框架展開。Executor 框架主要由三部分組成:

1. 任務

包括 Runnable 介面或 Callable 介面。Runnable 介面無返回值,Callable 有返回值。

// Runnable 和 Callable 都可以直接被 ThreadPoolExecutor 和 ScheduledThreadPoolExecutor 執行  Runnable runnable = () -> System.out.println(123);  // Executors 可以將 Runnable 轉化成 Callable  Callable<Object> callable = Executors.callable(runnable);  Callable<String> success = Executors.callable(runnable, "success");

2. 任務的執行

包括任務執行機制的核心介面 Executor、繼承自 Executor 的 ExecutorService 介面以及實現 ExecutorService 的 ThreadPoolExecutor 和 ScheduledThreadPoolExecutor。

ThreadPoolExecutor 是執行緒池的核心實現類,用來執行被提交的任務。其中 ThreadPoolExecutor 的原理就是上面介紹的執行緒池工作流程。

ScheduledThreadPoolExecutor 繼承自 ThreadPoolExecutor ,可以在給定的延遲後執行任務,或者定期執行任務。

Executors 是創建 ThreadPoolExecutor 和 ScheduledThreadPoolExecutor 的工廠類。

static ExecutorService executorService = Executors.newFixedThreadPool(5);

3. 非同步計算的結果

包括 Future 介面以及實現 Future 的 FutureTask 類。

// 執行 Runnable  executorService.execute(runnable);  // 執行 Callable  Future<Object> submit = executorService.submit(callable);  // Future 的 get 方法會阻塞執行緒直到完成  System.out.println(submit.get());  Future<String> future = executorService.submit(success);  System.out.println(future.get());

Executor 執行緒池的使用大抵如下,首先,我們需要創建 Runnable 或者 Callable 任務。然後通過 ThreadPoolExecutor.execute() 或者 ThreadPoolExecutor.submit() 把任務交給 ThreadPoolExecutor 容器執行。由 submit 提交的任務會返回 Future,表示執行緒執行的結果,其中 Future 的 get 方法會阻塞執行緒直到完成。

Executor框架的使用示意圖如下: