一、概念
fork-join 体现“分而治之”思想
将一个大任务分成N个子线程去处理,处理完成后将结果join合并
一个大任务分成2个线程AB执行,每个线程执行5个任务,当线程A执行完后,发现线程B的任务没执行完,那么线程A会去获取B的任务执行完并把结果返回到B中,这个情况叫窃取,提高的线程执行效率,不会使行线程A执行完任务后而空转
二、使用标准
使用标准范式:
pool = new ForkjoinPool()
task = new ForkTask
pool.inoke(forktask)
result = mytask.join()
三、例子
同步调用,有返回值:
统计一个单词在单词库出现的次数
public class LineTask extends RecursiveTask<Integer> {
private String line[];
private int start,end;
private String word;
public LineTask(String line[],int start,int end,String word){
this.line = line;
this.start = start;
this.end = end;
this.word = word;
}
@Override
protected Integer compute() {
Integer result = null;
if(end - start<=10){
return count(line,start,end,word);
}else{
int mid = (start + end)/2;
LineTask task1 = new LineTask(line,start,mid,word);
LineTask task2 = new LineTask(line,mid,end,word);
invokeAll(task1,task2);
result = task1.join() + task2.join();
return result;
}
}
private Integer count(String[] line,int start,int end,String word){
int counter;
counter = 0;
for(int i=start;i<end;i++){
if(line[i].equals(word)){
counter ++;
}
}
return counter;
}
public static void main(String[] args){
//初始化单词列表
String[] lines = new String[]{"word",
"fsdf","word4","word5","w4ord3",
"wo4rd3","wo4rd3","wo4rd3","wo4rd3",
"wo4rd3","wo4rd3","wo4rd3","wor4d3",
"wor4d3","wo4rd3","wor4d3","word43",
"w4ord3","wor4d3"};
//统计word在单词列表中的个数
LineTask task = new LineTask(lines,0,lines.length,"word");
ForkJoinPool pool = new ForkJoinPool();
Integer count = pool.invoke(task);//同步方法,会等到所有task返回
//如果execute(),异步方法
System.out.println("LineTask: The process has completed normally+"+count);
System.out.println("Main: The process has completed normally.\n");
System.out.println("Main: End of the program.\n");
}
}
异步调用,没有返回值
给商品批量涨价
public class Task extends RecursiveAction {
private List<Product> products;
private int first;
private int last;
private double increment;
public Task(List<Product> products,int first,int last,double increment){
this.products = products;
this.first = first;
this.last = last;
this.increment = increment;
}
@Override
protected void compute() {
if(last - first<10){
updateProducts();
}else{
int middle = (first+last)/2;
System.out.printf("Task: Pending tasks:%s\n",getQueuedTaskCount());
Task t1 = new Task(products,first,middle,increment);
Task t2 = new Task(products,middle+1,last,increment);
invokeAll(t1, t2);
}
}
public void updateProducts(){
for(int i = first;i<=last;i++){
Product product = products.get(i);
product.setPrice(product.getPrice()*(1+increment));
}
}
public static void main(String[] args){
ProductListGenerator productListGenerator = new ProductListGenerator();
List<Product> products = productListGenerator.generate(10);
Task task = new Task(products,0,products.size(),1);
ForkJoinPool pool = new ForkJoinPool();
pool.execute(task);//异步执行,主线程可以做其它事情
//doto something
task.join();//阻塞,只有当所有task子线程完成后,才执行下面代码
//有返回值可以拿返回值,没有返回值,可以不拿
for (int i=0; i<products.size(); i++){
Product product=products.get(i);
if (product.getPrice()!=12) {
System.out.printf("Product %s: %f\n",product.getName(),product.getPrice());
}
}
System.out.println("Main: End of the program.\n");
}
}