I would like to understand the order in which tasks are processed in Java fork-join pool.
So far, the only relevant information I've found in the docs is about a parameter called the "asyncMode", which is "true if this pool uses local first-in-first-out scheduling mode for forked tasks that are never joined".
My interpretation of this statement is that every worker has its own task queue; workers take tasks from the front of their own queue, or steal of the backs of other workers' queues if their own queues are empty; workers add newly-forked tasks to the back (resp. front) of their own queues if asyncMode is true (resp. false).
Please correct me if my interpretation is wrong!
Now, this raises a couple of questions:
1) What is the ordering for forked tasks that are joined?
My guess is that, when a task is forked, it is added to the worker's queue as described in my interpretation above. Now, suppose the task is joined...
If, when join is called, the task has not yet been started, the worker calling join will pull the task out of the queue and start working on it immediately.
If, when join is called, the task has already been stolen by another worker, then the worker calling join will work on other tasks in the meantime (following the ordering for getting tasks described in my interpretation above), until the task that it is joining has been finished by the worker that stole it.
This guess is based on writing simple test code with print statements, and observing the way in which changing the order of join calls influences the order in which tasks are processed. Could someone please tell me if my guess is correct?
2) What is the ordering for tasks that are submitted externally?
According to the answer to this question, fork-join pools do not use external queues. (I'm using Java 8, by the way.)
So am I to understand that when a task is submitted externally, the task is added to a randomly-selected worker queue?
If so, is the externally-submitted task added to the back or the front of the queue?
Finally, does this depend on whether the task is submitted by calling pool.execute(task) or by calling pool.invoke(task)? And does this depend on whether the thread calling pool.execute(task) or pool.invoke(task) is an external thread or a thread within this fork-join pool?