最近在看線程池代碼時發現了一個ForkJoinPool類,可以看一下線程池的繼承關系,頂層的Executor接口,提供了一個execute()方法,我們常用的ExecutorService接口也繼承自Executor接口,定義了一些額外的方法,下面呢就是AbstractExecutorService類,在這個類中實現了三個submit方法,而創建線程池的ThreadPoolExecutor類就繼承自AbstractExecutorService,而同時ForkJoinPool也繼承了AbstractExecutorService,對於這個ForkJoinPool以往不太了解,簡單學習了一下進行記錄。下面是線程池繼承體系。

ForkJoin並發框架是一個用於並行執行任務的框架,適用於計算密集型,它可以把一個任務分成若干個小任務,也可以把各個小任務的結果進行合並,所以很適合計算如從1加到100000這種操作。
ForkJoin並發框架:fork 分解任務 +join 將結果合並,當然,對於一些沒有返回結果的任務,可以只fork不合並。也就是僅僅fork划分任務,但不join進行任務結果的合並。
java中實現ForkJoin的幾個類
ForkJoinPool:繼承了線程池的接口,因此也是一種線程池的實現,不同之處在於我們平常創建的線程池只有一個任務隊列,而ForkJoinPool可以為每個線程分配任務隊列,同時一個線程可以從其他線程的任務隊列中獲取任務,因為有些線程可以很快的完成了任務,有些可能完成的比較慢,這是,完成快的就可以從完成慢的線程的任務隊列中獲取任務(從任務隊列后端獲取)。
ForkJoinTask:也就是ForkJoinPool要完成的任務,提供了fork和join 方法,有兩個常用的抽象子類RecursiveTask和RecursiveAction,都提供了抽象方法compute,我們可以重寫compute方法進行任務的划分,RecursiveTask提供返回值,而RecursiveAction不提供返回值。
通過一段代碼來理解forkjoin的用處和用法,計算從0加到10000000...。
定義一個類繼承RecursiveTask
public class ForkJoinCal extends RecursiveTask<Long> {
private long start;
private long end;
private static final long THRESHOLD = 10000L;//臨界值
public ForkJoinCal(long start, long end) {
this.start = start;
this.end = end;
}
@Override
protected Long compute() {
long length = end -start;
if(length<=THRESHOLD){
long sum =0;
for (long i = start; i <=end ; i++) {
sum+=i;
}
return sum;
}else {
long middle =(start+end)/2;
ForkJoinCal left = new ForkJoinCal(start, middle);
left.fork();
ForkJoinCal right = new ForkJoinCal(middle + 1, end);
right.fork();
return left.join()+right.join();
}
}
}
主方法進行測試
public class ForkJoinTest {
public static void main(String[] args) {
ForkJoinPool pool = new ForkJoinPool(2);
ForkJoinCal task = new ForkJoinCal(0, 1000000000L);
Long sum = pool.invoke(task);
System.out.println(sum);
}
}
本文暫時使了解ForkJoin是什么,怎么用,下面會對一些原理進行分析。
