首页 > 解决方案 > ForkJoinFramwork,无需显式 ForkJoinPool/ExecutorService 直接调用 compute()

问题描述

问:当直接调用扩展 RecursiveAction/Task 的类“X”中的 compute() 方法时会发生什么?

无需像下面这样显式调用 ForkJoinPool

ForkJoinPool pool = new ForkJoinPool();
ForkJoinTask<?> task = new X(...);
pool.invoke(task);

相反,像下面这样的函数调用仍然会产生类似的结果:

// X extends RecursiveAction/Task<V>, which also means it is a subclass of ForkJoinTask.
X x = new X(...);
x.compute();

当调用类 X 中的 fork()/invokeAll() 方法时会发生什么(显式 ExecutorService 不存在)?

我的假设是,当调用扩展类 X 中的 fork() 或 invoke() 方法时,如果没有明确指定池,则会自动将新任务提交给ForkJoinPool.commonPool() 。但我找不到任何指定此行为的文档。

(来自可能是相对的 oracle 文档的引用)

“主” ForkJoinTask 在显式提交到 ForkJoinPool 时开始执行,或者,如果尚未参与 ForkJoin 计算,则通过 fork()、invoke() 或相关方法在 ForkJoinPool.commonPool() 中开始执行。

任何信息或关键字将不胜感激。

代码片段(注意“othertask.fork()”):

class X extends RecursiveTask<Double>{
    private Double[] numbersToBeOperated;
    private int start;
    private int end;
    
    public X(Double numbersToBeOperated, int start, int end){
        // define the fields, i.e., this.* = *;
    }
    @Override
    protected Double compute(){
        if(taskDividedToBaseCase){
            // do works
        } else {
            int middle = start + ((end - start) / 2);
            RecursiveTask<Double> otherTask = new X(numbersToBeOperated, start, middle);
            otherTask.fork(); // what happens here, when compute() is directly called?
            return new X(numbersToBeOperated, middle, end).compute() + otherTask.join();
            // or invokeAll(new X(...), new X(...)); if RecursiveAction
        }
    }
}
// then instantiate X and call X.compute() directly. 

标签: javaconcurrencyforkjoinpool

解决方案


引用java.util.concurrent.ForkJoinTask<V>.fork()

安排在当前任务正在运行的池中异步执行此任务(如果适用),或者如果不是 inForkJoinPool(),则使用 ForkJoinPool.commonPool()。

它确实进入了 commonPool()。

还要感谢@Holger 指向此文档。


推荐阅读