My question can best be explained by giving a code snippet:
public static void main(final String[] a) {
Stream.of(1, 2, 3, 4).map(i -> ForkJoinPool.commonPool().submit(new RecursiveAction() {
@Override
protected void compute() {
System.out.println(Thread.currentThread());
}
})).forEach(ForkJoinTask::join);
}
When running this on my laptop, which has 4 cores, this prints:
Thread[main,5,main]
Thread[ForkJoinPool.commonPool-worker-1,5,main]
Thread[main,5,main]
Thread[ForkJoinPool.commonPool-worker-1,5,main]
Why are certain tasks ran in the main thread, which is a thread outside the common fork join thread pool?
When creating a custom fork join thread pool, this is not happening:
public static void main(final String[] a) {
final ForkJoinPool p = new ForkJoinPool(4);
Stream.of(1, 2, 3, 4).map(index -> p.submit(new RecursiveAction() {
@Override
protected void compute() {
System.out.println(Thread.currentThread());
}
})).forEach(ForkJoinTask::join);
}
Thread[ForkJoinPool-1-worker-1,5,main]
Thread[ForkJoinPool-1-worker-1,5,main]
Thread[ForkJoinPool-1-worker-1,5,main]
Thread[ForkJoinPool-1-worker-1,5,main]
So, in other words, what is special about the common pool? Giving this knowledge, would it be a wise or unwise idea to execute long-running tasks in the common pool?
Something rather clever happens.
When you call
ForkJoinTask::join
from a thread that is not in the thread, it appears (from the comment onForkJoinPool.awaitJoin
) that current thread can "helps" with task execution.So that's why the main thread is executing tasks in the fork-join pool.
But why is it different in the case where you created a custom pool? Well, my guess is that your custom pool has enough threads that the main thread is not needed. Because the other thing is that by default the "common pool" is created with one thread fewer than the number of available processors.
For more details look at the source code. Note that this behavior is not specified in the javadocs, so it could change in future implementations.