ForkJoinPool 實作 ExecutorService,專為 **分治遞歸任務** 設計。核心創新:**Work-Stealing(工作盜竊)演算法** —— 空閒執行緒從忙碌執行緒雙端佇列「偷」任務,極大提升多核利用率。
ForkJoinPool:執行引擎,管理工作執行緒與任務佇列ForkJoinTask<V>:任務基類
RecursiveTask<V>:有返回值RecursiveAction:無返回值protected void compute() {
if (taskSmallEnough()) {
computeDirectly(); // 基礎情況:直接計算
} else {
ForkJoinTask<V> left = createSubtask();
ForkJoinTask<V> right = createSubtask();
left.fork(); // 非阻塞提交左子任務
V rightResult = right.compute(); // 當前執行緒執行右子任務
V leftResult = left.join(); // 等待左子任務完成
return combine(leftResult, rightResult);
}
}
將像素陣列遞歸二分,閾值 sThreshold = 100_000 像素以下直接計算:
public class ForkBlur extends RecursiveAction {
private final int[] src, dst;
private final int start, len;
private static final int BLUR_WIDTH = 15;
private static final int THRESHOLD = 100_000;
protected void compute() {
if (len < THRESHOLD) { computeDirectly(); return; }
int split = len / 2;
invokeAll(new ForkBlur(src, start, split, dst),
new ForkBlur(src, start + split, len - split, dst));
}
// computeDirectly() 實作像素鄰域平均...
}
啟動:new ForkJoinPool().invoke(new ForkBlur(src, 0, src.length, dst));
Arrays.parallelSort()、parallelPrefix():JDK 8+ 內部使用 Fork/JoinStream.parallel():ForkJoinPool.commonPool() 執行並行流水線| 參數 | 建議 |
|---|---|
| 並行度 | 預設 Runtime.getRuntime().availableProcessors();IO 密集可調大 |
| 任務粒度 | 太細 → 任務管理開銷大;太粗 → 負載不均。典型 10k-100k 基本操作 |
| 閾值調整 | 基準測試尋找甜點;可依硬體動態計算 |
| ManagedBlocker | 阻塞操作(IO、鎖)實作此介面避免佔用工作執行緒 |
Thread.sleep、同步 IO、重鎖 → 導致工作執行緒餓死fork() 子任務異常需 join() 時拋出,或覆寫 onExceptionalCompletioncommonPool 執行長時間/阻塞任務 → 影響全應用並行流Fork/Join 讓分治遞歸並行化變得簡單高效,是多核時代 Java 開發者必備利器。