Remark on the StructuredTaskScope API of Java 25

forax at univ-mlv.fr forax at univ-mlv.fr
Thu Sep 25 05:38:41 UTC 2025


> From: "David Alayachew" <davidalayachew at gmail.com>
> To: "Alan Bateman" <alan.bateman at oracle.com>
> Cc: "Remi Forax" <forax at univ-mlv.fr>, "loom-dev" <loom-dev at openjdk.java.net>
> Sent: Wednesday, September 24, 2025 9:06:41 PM
> Subject: Re: Remark on the StructuredTaskScope API of Java 25

> > If the API allowed Subtask::get to be used
> > before join then it would be very fragile as it
> > would be like a "wait-less" Future::get. It
> > might work sometimes, but if a subtask were
> > slow then Subtask::get would throw ISE.

> Can you explain this in more detail? I don't understand what you are saying
> here.

Actually, you can not extract the values using the main from any subtasks until STS.join() complete, 
there is a specail check is Subtask.get() that check that if you are the main thread, join has to be called before. 

So if you write, 

try(var sts = STS.open()) { 
var subtask = sts.fork(callable); 

// we are before the join here 
IO.println(subtask.get()); 
// here you have a race between the main thread and the virtual thread that run the callable 
// so you can get spurious IllegalStateException 
// to make the user aware of that, SubTask.get() has a special case that throw is get() is called by the main thread before join() 
sts.join(); 

IO.println(subtask.get()); // this is fine, we are after the join(). 
} 

The problem, is that this check is a kind of weak, because you can write 

try(var sts = STS.open()) { 
var subtask = sts.fork(callable); 

// spurious STS are back ! 
Thread.ofVirtual().start(() -> IO.println(subtask.get())).join(); 

sts.join(); 
} 

regards, 
Rémi 

> On Wed, Sep 24, 2025 at 1:52 PM Alan Bateman < [ mailto:alan.bateman at oracle.com
> | alan.bateman at oracle.com ] > wrote:

>> On 24/09/2025 16:37, Remi Forax wrote:

>>> :

>>> And now two remarks,
>>> - is there a way to remove the limitation that the main thread (the one that
>>>  have created the STS) can not access to SubTask.get(),
>>>   because there is at least a case where i know that the task is finished before
>>>    join() is called (see below).

>> This restriction is there to ensure that the API is used as intended. Subtasks
>> are forked individually and then joined as a unit. If the API allowed
>> Subtask::get to be used before join then it would be very fragile as it would
>> be like a "wait-less" Future::get. It might work sometimes, but if a subtask
>> were slow then Subtask::get would throw ISE.

>>> - is there a way to get a joiner that returns the list of subtask in the order
>>> if their completeness, not in the order of onFork() ?

>> A Joiner can collect in its onComplete method so that will give you completion
>> order. That said, I suspect you might be asking something different. Are you
>> thinking about APIs such as CompletionService where you get a wakeup as
>> subtasks complete rather join as a unit?

>> -Alan
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/loom-dev/attachments/20250925/d5972052/attachment-0001.htm>


More information about the loom-dev mailing list