什么是Fork/Join
Java提供了ForkJoinPool线程池,你可以向该线程池里提交一个ForkJoinTask任务。而这个ForkJoinTask就支持Fork(分解)和Join(等待)的功能。简而言之就是采用分治法,将一个任务分解为多个子任务,最后将多个子任务计算的结果归并,像不像Hadoop里的Mapreduce。
如何使用Fork/Join
- 首先创建ForkJoinPool线程池:
ForkJoinPool pool = new ForkJoinPool();
- 接着创建一个ForkJoinPool,通过ForkJoinTask接口下的submit函数提交任务。‘
public <T> ForkJoinTask<T> submit(ForkJoinTask<T> task) {
ForkJoinTask拥有两个子类:RecursiveTask和RecursiveAction。其中RecursiveTask是能够返回值的,而RecursiveAction是无返回值的。
- 创建一个任务类,通过继承RecursiveTask或RecursiveAction。
- 重写compute方法,compute内的主要功能是完成计算任务、对任务进行拆分。
代码示例
import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
public class Main extends RecursiveTask<Long> {
private static final int THRESHOLD = 10000;
private long start;
private long end;
public Main(long start, long end) {
this.start = start;
this.end = end;
}
public static void main(String[] args) {
ForkJoinPool pool = new ForkJoinPool();
Main task = new Main( 0, 200000L );
ForkJoinTask<Long> res = pool.submit( task );
try {
long r = res.get();
System.out.println( r );
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
@Override
protected Long compute() {
long sum = 0;
//计算范围是否小于限定范围
boolean canCompute = (end - start) < THRESHOLD;
//小于直接求和
if (canCompute) {
for (long i = start; i <= end; i++) {
sum += i;
}
}
//大于等于时
else {
long step = (start + end) / 100;
ArrayList<Main> subTasks = new ArrayList<>();
long pos = start;
for (int i = 0; i < 100; i++) {
long lastOne = pos + step;
if (lastOne > end) {
lastOne = end;
}
Main subTask = new Main( pos, lastOne );
pos += step + 1;
subTasks.add( subTask );
subTask.fork();
}
for (Main t : subTasks) {
sum += t.join();
}
}
return sum;
}
}