As far as I had understood ForkJoinPool
, that pool creates a fixed number of threads (default: number of cores) and will never create more threads (unless the a
The both code snippets posted by Holger Peine and elusive-code doesn't actually follow recommended practice which appeared in javadoc for 1.8 version:
In the most typical usages, a fork-join pair act like a call (fork) and return (join) from a parallel recursive function. As is the case with other forms of recursive calls, returns (joins) should be performed innermost-first. For example, a.fork(); b.fork(); b.join(); a.join(); is likely to be substantially more efficient than joining code a before code b.
In both cases FJPool was instantiated via default constructor. This leads to construction of the pool with asyncMode=false, which is default:
@param asyncMode if true,
establishes local first-in-first-out scheduling mode for forked tasks that are never joined. This mode may be more appropriate than default locally stack-based mode in applications in which worker threads only process event-style asynchronous tasks. For default value, use false.
that way working queue is actually lifo:
head -> | t4 | t3 | t2 | t1 | ... | <- tail
So in snippets they fork() all task pushing them on stack and than join() in same order, that is from deepest task (t1) to topmost (t4) effectively blocking until some other thread will steal (t1), then (t2) and so on. Since there is enouth tasks to block all pool threads (task_count >> pool.getParallelism()) compensation kicks in as Louis Wasserman described.