- Fork是对任务的分解,Join对应结果合并
- Fork/Join计算框架主要包含两部分,一部分是分治任务的线程池ForkJoinPool,另一部分是ForkJoinTask。类似ThreadPoolExecutor和Runnable的关系。
- ForkJoinTask有两个子类-- RecursiveAction和RecursiveTask,都定义了抽象方法compute() ,RecursiveTask的compute()有返回值。
- ForkJoinPool工作原理:
- 内部有多个 工作队列, 当调用 ForkJoinPool的 submit()或invoke()提交任务,ForkJoinPool会根据一定的路由规则把任务提交到一个任务队列中,如果任务在执行过程中会创建出子任务,那么子任务会提交到工作线程对应的任务队列中。
- 支持工作窃取
- 斐波那契数列
package forkjoin;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
class Fibtask extends RecursiveTask<Integer>{
final int n;
Fibtask(int n)
{
this.n = n;
}
@Override
protected Integer compute() {
if (n<=1)return n;
Fibtask f1 = new Fibtask(n-1);
f1.fork();
Fibtask f2 = new Fibtask(n-2);
return f2.compute()+ f1.join();
}
}
public class FibV2 {
public static void main(String[] args) {
Long start = System.currentTimeMillis();
ForkJoinPool forkJoinPool = new ForkJoinPool(1);
Integer res = forkJoinPool.invoke(new Fibtask(33));
System.out.println(res);
Long end = System.currentTimeMillis();
System.out.println(end-start);
}
}
- 统计词频
package forkjoin;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
class MR extends RecursiveTask<Map<String,Long>>{
private String[]fc;
private int start,end;
public MR(String[]fc, int start,int end)
{
this.fc = fc;
this.start = start;
this.end = end;
}
@Override
protected Map<String, Long> compute() {
if (start==end)
{
return calc(fc[start]);
}else {
int mid = (start + end)/2;
MR f1 = new MR(fc,start,mid);
f1.fork();
MR f2 = new MR(fc,mid+1,end);
return merge(f1.join(),f2.compute());
}
}
private Map<String,Long>merge(Map<String,Long>r1,Map<String,Long>r2)
{
Map<String,Long>res = new HashMap<>();
res.putAll(r1);
r2.forEach((k,v)->{res.put(k,res.getOrDefault(k,0L)+v);});
return res;
}
private Map<String,Long>calc(String line)
{
Map<String,Long>result = new HashMap<>();
String[]words = line.split("\\s+");
for (String w:words)
{
result.put(w,result.getOrDefault(w,0L)+1);
}
return result;
}
}
public class countFreq {
public static void main(String[] args) {
Long start = System.currentTimeMillis();
String[]fc = {"hello world","hello me","hello fork","hello join","fork join in world"};
ForkJoinPool forkJoinPool = new ForkJoinPool();
Map<String,Long>res = forkJoinPool.invoke(new MR(fc,0,fc.length-1));
res.forEach((k,v)->{
System.out.println(String.format("%s freq: %d",k,v));
});
Long end = System.currentTimeMillis();
System.out.println(end-start);
}
}