1.关于ForkJoin的基础知识理解:
http://tutorials.jenkov.com/java-util-concurrent/java-fork-and-join-forkjoinpool.html
2.个人理解:
public class Main {
public static void main(String[] args) throws InterruptedException {
MyRecursiveAction myRecursiveAction = new MyRecursiveAction(24);//MyRecursiveAction类的实现在上面的URL中
myRecursiveAction.fork();
TimeUnit.SECONDS.sleep(10);//这个睡眠是为了观察action执行compute的时机
myRecursiveAction.join();
}
}
2-1. fork:
myRecursiveAction.fork();
按照fork join的模型,大任务首先要分解成小任务,当执行myRecursiveAction.fork()时,会创建worker线程:ForkJoinWorkerThread,这个worker线程就会执行提交的任务。但是分解任务的方法不是自动的,需要代码处理,如下:
@Override
protected void compute() {
//if work is above threshold, break tasks up into smaller tasks
if(this.workLoad > 16) {
System.out.println("Splitting workLoad : " + this.workLoad);
List<MyRecursiveAction> subtasks =
new ArrayList<MyRecursiveAction>();
subtasks.addAll(createSubtasks());
for(RecursiveAction subtask : subtasks){
subtask.fork();
}
} else {
System.out.println("Doing workLoad myself: " + this.workLoad);
}
}
这个compute方法就是要执行的具体任务,但是在分解任务中,这个本来要执行的具体任务变成了执行分解的任务。
2-2. join:
myRecursiveAction.join();
这个方法等待所有的任务执行完成之后,但是要注意的是,当fork的compute方法执行任务分解时,可能需要等待子任务(就是被分解之后的任务)完成,这时需要在compute中调用join方法,否则最外层调用的join方法返回时,完成的只是部分任务。(参照上面的URL里面的RecursiveTask使用方法)。
2-3. 使用时注意事项:
注意deadlock,如在compute中分解任务task->subtask,然后对subtask继续fork,再对subtask执行join方法,因为该worker会等待join方法完成,但是subtask的fork方法又在等待该worker线程的释放,此时可能发生deadlock。(这个场景并没有实际验证过,仅仅是猜测。)