ForkJoin框架,直接调用compute(),无需显式ForkJoinPool/ExecutorService。

huangapple go评论72阅读模式
英文:

ForkJoinFramwork, call compute() directly without explicit ForkJoinPool/ExecutorService

问题

Q: 当直接调用一个扩展了RecursiveAction/Task<V>的类"X"中的compute()方法时会发生什么?

不像下面这样显式地调用ForkJoinPool

ForkJoinPool pool = new ForkJoinPool();
ForkJoinTask&lt;?&gt; task = new X(...);
pool.invoke(task);

而是像下面这样调用一个函数,仍然会产生类似的结果:

// X扩展了RecursiveAction/Task&lt;V&gt;,这也意味着它是ForkJoinTask的子类。
X x = new X(...);
x.compute();

当在类X内部调用fork() / invokeAll()方法时(没有显式指定ExecutorService),会发生什么?

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

(可能相关的Oracle文档引用)
> 当"main" ForkJoinTask 被显式地提交到ForkJoinPool时,或者如果它尚未参与ForkJoin计算,则通过fork()、invoke()或相关方法在ForkJoinPool.commonPool()中开始执行。

如果有任何信息或关键词,将不胜感激。

一个代码片段(注意"othertask.fork()"):

class X extends RecursiveTask&lt;Double&gt;{
    private Double[] numbersToBeOperated;
    private int start;
    private int end;
    
    public X(Double numbersToBeOperated, int start, int end){
        // 定义字段,即this.* = *;
    }
    @Override
    protected Double compute(){
        if(taskDividedToBaseCase){
            // 做一些操作
        } else {
            int middle = start + ((end - start) / 2);
            RecursiveTask&lt;Double&gt; otherTask = new X(numbersToBeOperated, start, middle);
            otherTask.fork(); // 在直接调用compute()时这里会发生什么?
            return new X(numbersToBeOperated, middle, end).compute() + otherTask.join();
            // 或者如果是RecursiveAction,使用invokeAll(new X(...), new X(...));
        }
    }
}
// 然后实例化X并直接调用X.compute()。 
英文:

Q: What happens when the compute() method, in a class "X" that extends RecursiveAction/Task<V>, is directly called?

Without calling a ForkJoinPool explicitly like the following:

ForkJoinPool pool = new ForkJoinPool();
ForkJoinTask&lt;?&gt; task = new X(...);
pool.invoke(task);

Instead a function call like the following still produce a similar result:

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

What happens when the fork()/invokeAll() method inside class X is called (explicit ExecutorService is absent)?

My assumption would be, when an fork() or invoke() method inside the extended class X is called, a new task is automatically submitted to the ForkJoinPool.commonPool(), if no pool is explicitly specified. But I couldn't find any document that specifies this behavior.

(Citation from the oracle documentation that might be relative)
> A "main" ForkJoinTask begins execution when it is explicitly submitted
> to a ForkJoinPool, or, if not already engaged in a ForkJoin
> computation, commenced in the ForkJoinPool.commonPool() via fork(),
> invoke(), or related methods.

Any info or keywords would be appreciated.

A code snippet (note the "othertask.fork()"):

class X extends RecursiveTask&lt;Double&gt;{
    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&lt;Double&gt; 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. 

答案1

得分: 2

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

如果适用,安排在当前任务所在的池中异步执行此任务,否则使用ForkJoinPool.commonPool(),如果不在ForkJoinPool()中。

它确实会进入commonPool()。

还要感谢 @Holger 指出了这份文档。

英文:

Citing java.util.concurrent.ForkJoinTask&lt;V&gt;.fork():
> Arranges to asynchronously execute this task in the pool the current task is running in, if applicable, or using the
> ForkJoinPool.commonPool() if not inForkJoinPool().

It do goes to the commonPool().

Also thanks @Holger for pointing to this documentation.

huangapple
  • 本文由 发表于 2020年8月24日 07:42:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/63553074.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定