[concurrency-interest] ForkJoin updates

Doug Lea dl at cs.oswego.edu
Thu Jan 26 09:35:24 EST 2012

A few further followups of list discussions that led
to some of the updates:

* The ForkJoinWorkerThreadFactory interface is unchanged.
Even though it might be more convenient for some to
create a subinterface with a callback when a worker
thread terminates, there's not enough motivation to
do so considering that these threads cannot be reused.
As I mentioned in posts about this, it is OK for
Factories to limit thread creation by returning null
when they don't want to create more. Although if
they do so when there are fewer threads than the
parallelism level, the will be frequently asked to
provide one, which may end up slowing things down a lot.

* I also resisted the temptation to re-introduce a
"maintainParallelism" method to force creation of
additional workers when some but not all tasks are blocked.
I do not know how to support this in a way that
is not prone to unwanted positive feedback loops that
will tend to create unexpectedly high numbers of threads.
It is by far better for users to use the ManagedBlocker
API to issue advisories that we can internally use
to throttle threads, and further improve how we do so.

* The new version is much more likely than the previous
one to process submissions out of order. Nothing was
ever guaranteed about this but it is possible that
some users mistook the previously low probability
of out-of-order processing for "never". Also, the
previous version had a different bypass for
self-submissions, which can also impact processing
order, but is still within spec.

* I had written...
> One way to address this is to use a "claim" bit on
> every task (somewhat similar to your execJoin workaround).

This is one possible use of new task-marking methods,
People who need to claim tasks because of lack of static
dag structure can do so without adding to overhead in other

* A few of the status/inspection
methods are a bit slower and may require traversals
through multiple queues/workers. In particular,
getActiveThreadCount() remains O(1) and atomic, but
getRunningThreadCount(), that estimates the number of
threads that are not somehow blocked, now probes
the thread state of each worker, which is slower
but typically more accurate than previous version
because it relies on JVM Thread.State, that knows
that threads are blocked even when the pool does not.


More information about the Concurrency-interest mailing list