When should we call join() after ForkJoinTask.invokeAll()

Tags: , ,



The API says: “Method invokeAll (available in multiple versions) performs the most common form of parallel invocation: forking a set of tasks and joining them all.”

So my assumption is if I use invokeAll(), I no longer need to use fork() or join() methods. I also know that in general, join() is called only if the task returns a value: a subclass of: RecursiveTask and not used if the task not returning a value: subclass of: RecursiveAction.

I came across this tutorial which has called ForkJoinTask.join() after its called: invokeAll():

https://www.baeldung.com/java-fork-join

@Override
    protected Integer compute() {
        if (arr.length > THRESHOLD) {
            return ForkJoinTask.invokeAll(createSubtasks())
              .stream()
              .mapToInt(ForkJoinTask::join) // join() is called
              .sum();
        } else {
            return processing(arr);
        }
    }

Also this post, which has used join() after calling invokeAll():

Why should we call join after invokeAll method?

invokeAll(subTask1, subTask2);

return subTask1.join() + subTask2.join();

At the same time, I looked at many other examples for invokeAll() and there is NO join() after that call.

1) Is there any rule that when we should or should not use join() after invokeAll()?

2) invokeAll() comes in three different signatures, is this depending on the signature of the method to decide whether to use join() or not?

3) On the same note, I also read this in the API:

“Method invoke() is semantically equivalent to fork(); join() but always attempts to begin execution in the current thread.”

Is it saying that invoke() is equal to fork() plus join()?

Answer

  1. Call join() when you need the results of the computation. There is no rule regarding when. If you have other work to do you can do that, if you have no other work to do and you need the results from the computation, call join()

  2. The signatures reflect the different ways of supplying the tasks. With one they come from a collection, with another they come from varargs or an array, with the third you supply two as arguments. Otherwise there is no difference between them. Use the one that is most convenient.

  3. fork(); join() is asynchronous, the work by fork is in another thread and the current thread waits for the work to complete when join is called. invoke() does the same work but in the current thread.



Source: stackoverflow