fork/join框架介紹
在jdk中,給我們提供了一種類似於MapReduce的編程模型。用於把一個大的任務拆分成多個小任務單元,分配到多個線程去併發執行,再把各最小單元的返回的結果聚合返回。這樣一來,對於大任務的執行效率就大大提升了。下面我以一個簡單的例子來介紹一下api的使用。
實例展示
業務需求:把從1到100個數依次相加,返回最終的結果。
業務分析:把100個數拆分成10組,每組10個元素來執行計算。使用RecursiveTask類來實現。
代碼展示:
/**
* 多線程併發求和
*
* @author cobee
* @since 2020-02-28
*/
public class SumJob extends RecursiveTask<Integer> {
// 存放元素的list集合
private List<Integer> elems;
private int start;
private int end;
public SumJob(List<Integer> elems, int start, int end) {
this.elems = elems;
this.start = start;
this.end = end;
}
@Override
protected Integer compute() {
int interval = end - start;
// 以10個爲一組計算,執行任務,最小執行單元
if(interval <= 10){
int sum = 0;
for(int i = start; i < end; i++){
sum += elems.get(i);
}
return sum;
}else{
// 繼續拆分,直到拆分到最小的執行單元
int x = (end + start) / 2;
SumJob job1 = new SumJob(elems, start, x);
job1.fork(); // 任務拆分
SumJob job2 = new SumJob(elems, x, end);
job2.fork(); // 任務拆分
// 合併結果
Integer join1 = job1.join();
Integer join2 = job2.join();
return join1 + join2;
}
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
List<Integer> elems = new ArrayList<>();
int sum = 0;
for(int i = 1; i <= 100; i++){
elems.add(i);
sum += i;
}
System.out.println("for sum:" + sum);
SumJob job = new SumJob(elems, 0, elems.size());
ForkJoinPool forkJoinPool = new ForkJoinPool(5, ForkJoinPool.defaultForkJoinWorkerThreadFactory, null, true);
ForkJoinTask<Integer> forkJoinTask = forkJoinPool.submit(job);
System.out.println("forkJoin sum:" + forkJoinTask.get());
}
}
總結
java的fork/join框架使用簡單。關鍵有三個點:第一,如何根據業務來定義你的任務;第二,如何拆分任務;第三,如何合併子任務的結果。