Interface StructuredTaskScope.Joiner<T,R>
- Type Parameters:
T
- the result type of subtasks executed in the scopeR
- the result type of the scope
- Enclosing interface:
StructuredTaskScopePREVIEW<T,
R>
- Functional Interface:
- This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.
Joiner
is a preview API of the Java platform.
StructuredTaskScope
PREVIEW to handle subtask completion and
produce the result for the scope owner waiting in the join
PREVIEW method
for subtasks to complete.
Joiner defines static methods to create Joiner
objects for common cases:
-
allSuccessfulOrThrow()
creates aJoiner
that yields a stream of the completed subtasks forjoin
to return when all subtasks complete successfully. It cancels the scope and causesjoin
to throw if any subtask fails. -
anySuccessfulResultOrThrow()
creates aJoiner
that yields the result of the first subtask to succeed forjoin
to return. It causesjoin
to throw if all subtasks fail. -
awaitAllSuccessfulOrThrow()
creates aJoiner
that waits for all successful subtasks. It cancels the scope and causesjoin
to throw if any subtask fails. -
awaitAll()
creates aJoiner
that waits for all subtasks. It does not cancel the scope or causejoin
to throw.
In addition to the methods to create Joiner
objects for common cases,
the allUntil(Predicate)
method is defined to create a
Joiner
that yields a stream of all subtasks. It is created with a Predicate
that determines if the scope should continue or be cancelled.
This Joiner
can be built upon to create custom policies that cancel the
scope based on some condition.
More advanced policies can be developed by implementing the Joiner
interface. The onFork(Subtask)
method is invoked when subtasks are forked.
The onComplete(Subtask)
method is invoked when subtasks complete with a
result or exception. These methods return a boolean
to indicate if scope
should be cancelled. These methods can be used to collect subtasks, results, or
exceptions, and control when to cancel the scope. The result()
method
must be implemented to produce the result (or exception) for the join
method.
Unless otherwise specified, passing a null
argument to a method
in this class will cause a NullPointerException
to be thrown.
- API Note:
- It is very important that a new
Joiner
object is created for eachStructuredTaskScope
.Joiner
objects should never be shared with different scopes or re-used after a task is closed.Designing a
Joiner
should take into account the code at the use-site where the results from thejoin
PREVIEW method are processed. It should be clear what theJoiner
does vs. the application code at the use-site. In general, theJoiner
implementation is not the place to code "business logic". AJoiner
should be designed to be as general purpose as possible. - Implementation Requirements:
- Implementations of this interface must be thread safe. The
onComplete(Subtask)
method defined by this interface may be invoked by several threads concurrently. - Since:
- 24
- See Also:
-
Method Summary
Modifier and TypeMethodDescriptionstatic <T> StructuredTaskScope.JoinerPREVIEW
<T, Stream<StructuredTaskScope.SubtaskPREVIEW<T>>> Returns a new Joiner object that yields a stream of all subtasks when all subtasks complete successfully.static <T> StructuredTaskScope.JoinerPREVIEW
<T, Stream<StructuredTaskScope.SubtaskPREVIEW<T>>> allUntil
(Predicate<StructuredTaskScope.SubtaskPREVIEW<? extends T>> isDone) Returns a new Joiner object that yields a stream of all subtasks when all subtasks complete or a predicate returnstrue
to cancel the scope.static <T> StructuredTaskScope.JoinerPREVIEW
<T, T> Returns a new Joiner object that yields the result of any subtask that completed successfully.static <T> StructuredTaskScope.JoinerPREVIEW
<T, Void> awaitAll()
Returns a new Joiner object that waits for all subtasks to complete.static <T> StructuredTaskScope.JoinerPREVIEW
<T, Void> Returns a new Joiner object that waits for subtasks to complete successfully.default boolean
onComplete
(StructuredTaskScope.SubtaskPREVIEW<? extends T> subtask) Invoked by the thread started to execute a subtask after the subtask completes successfully or fails with an exception.default boolean
onFork
(StructuredTaskScope.SubtaskPREVIEW<? extends T> subtask) result()
-
Method Details
-
onFork
Invoked byfork(Callable)
PREVIEW andfork(Runnable)
PREVIEW when forking a subtask. The method is invoked from the task owner thread. The method is invoked before a thread is created to run the subtask.- API Note:
- This method is invoked by the
fork
methods. It should not be invoked directly. - Implementation Requirements:
- The default implementation throws
NullPointerException
if the subtask isnull
. It throwsIllegalArgumentException
if the subtask is not in theUNAVAILABLE
PREVIEW state, it otherwise returnsfalse
. - Parameters:
subtask
- the subtask- Returns:
true
to cancel the scope, otherwisefalse
-
onComplete
Invoked by the thread started to execute a subtask after the subtask completes successfully or fails with an exception. This method is not invoked if a subtask completes after the scope is cancelled.- API Note:
- This method is invoked by subtasks when they complete. It should not be invoked directly.
- Implementation Requirements:
- The default implementation throws
NullPointerException
if the subtask isnull
. It throwsIllegalArgumentException
if the subtask is not in theSUCCESS
PREVIEW orFAILED
PREVIEW state, it otherwise returnsfalse
. - Parameters:
subtask
- the subtask- Returns:
true
to cancel the scope, otherwisefalse
-
result
Invoked by thejoin()
PREVIEW method to produce the result (or exception) after waiting for all subtasks to complete or the scope cancelled. The result from this method is returned by thejoin
method. If this method throws, thenjoin
throwsStructuredTaskScope.FailedException
PREVIEW with the exception thrown by this method as the cause.In normal usage, this method will be called at most once by the
join
method to produce the result (or exception). The behavior of this method when invoked directly, and invoked more than once, is not specified. Where possible, an implementation should return an equal result (or throw the same exception) on second or subsequent calls to produce the outcome.- API Note:
- This method is invoked by the
join
method. It should not be invoked directly. - Returns:
- the result
- Throws:
Throwable
- the exception
-
allSuccessfulOrThrow
static <T> StructuredTaskScope.JoinerPREVIEW<T,Stream<StructuredTaskScope.SubtaskPREVIEW<T>>> allSuccessfulOrThrow()Returns a new Joiner object that yields a stream of all subtasks when all subtasks complete successfully. TheJoiner
cancels the scope and causesjoin
to throw if any subtask fails.If all subtasks complete successfully, the joiner's
result()
method returns a stream of all subtasks in the order that they were forked. If any subtask failed then theresult
method throws the exception from the first subtask to fail.- API Note:
- Joiners returned by this method are suited to cases where all subtasks
return a result of the same type. Joiners returned by
awaitAllSuccessfulOrThrow()
are suited to cases where the subtasks return results of different types. - Type Parameters:
T
- the result type of subtasks- Returns:
- a new Joiner object that yields a stream of all subtasks when all subtasks complete successfully
-
anySuccessfulResultOrThrow
Returns a new Joiner object that yields the result of any subtask that completed successfully. TheJoiner
causesjoin
to throw if all subtasks fail.The joiner's
result()
method returns the result of a subtask that completed successfully. If all subtasks fail then theresult
method throws the exception from one of the failed subtasks. Theresult
method throwsNoSuchElementException
if no subtasks were forked.- Type Parameters:
T
- the result type of subtasks- Returns:
- a new Joiner object that yields the result of any subtask that completed successfully
-
awaitAllSuccessfulOrThrow
Returns a new Joiner object that waits for subtasks to complete successfully. TheJoiner
cancels the scope and causesjoin
to throw if any subtask fails.The joiner's
result
method returnsnull
if all subtasks complete successfully, or throws the exception from the first subtask to fail.- API Note:
- Joiners returned by this method are suited to cases where subtasks
return results of different types. Joiners returned by
allSuccessfulOrThrow()
are suited to cases where the subtasks return a result of the same type. - Type Parameters:
T
- the result type of subtasks- Returns:
- a new Joiner object that waits for subtasks to complete successfully
-
awaitAll
Returns a new Joiner object that waits for all subtasks to complete. TheJoiner
does not cancel the scope if a subtask fails.The joiner's
result
method returnsnull
.- API Note:
- This Joiner is useful for cases where subtasks make use of
side-effects rather than return results or fail with exceptions.
The
fork(Runnable)
PREVIEW method can be used to fork subtasks that do not return a result.This Joiner can also be used for fan-in scenarios where subtasks for forked to handle incoming connections and the number of subtasks is unbounded. In this example, the thread executing the
acceptLoop
method will only stop when interrupted or the listener socket is closed asynchronously.void acceptLoop(ServerSocket listener) throws IOException, InterruptedException { try (var scope = StructuredTaskScope.open(Joiner.<Socket>awaitAll())) { while (true) { Socket socket = listener.accept(); scope.fork(() -> handle(socket)); } } }
- Type Parameters:
T
- the result type of subtasks- Returns:
- a new Joiner object that waits for all subtasks to complete
-
allUntil
static <T> StructuredTaskScope.JoinerPREVIEW<T,Stream<StructuredTaskScope.SubtaskPREVIEW<T>>> allUntil(Predicate<StructuredTaskScope.SubtaskPREVIEW<? extends T>> isDone) Returns a new Joiner object that yields a stream of all subtasks when all subtasks complete or a predicate returnstrue
to cancel the scope.The joiner's
onComplete(Subtask)
method invokes the predicate'stest
method with the subtask that completed successfully or failed with an exception. If thetest
method returnstrue
then the scope is cancelled. Thetest
method must be thread safe as it may be invoked concurrently from several threads.The joiner's
result()
method returns the stream of all subtasks, in fork order. The stream may contain subtasks that have completed (inSUCCESS
PREVIEW orFAILED
PREVIEW state) or subtasks in theUNAVAILABLE
PREVIEW state if the scope was cancelled before all subtasks were forked or completed.The following example uses this method to create a
Joiner
that cancels the scope when two or more subtasks fail.class CancelAfterTwoFailures<T> implements Predicate<Subtask<? extends T>> { private final AtomicInteger failedCount = new AtomicInteger(); @Override public boolean test(Subtask<? extends T> subtask) { return subtask.state() == Subtask.State.FAILED && failedCount.incrementAndGet() >= 2; } } var joiner = Joiner.all(new CancelAfterTwoFailures<String>());
The following example uses
allUntil
to wait for all subtasks to complete without any cancellation. This is similar toawaitAll()
except that it yields a stream of the completed subtasks.<T> List<Subtask<T>> invokeAll(Collection<Callable<T>> tasks) throws InterruptedException { try (var scope = StructuredTaskScope.open(Joiner.<T>allUntil(_ -> false))) { tasks.forEach(scope::fork); return scope.join().toList(); } }
- Type Parameters:
T
- the result type of subtasks- Parameters:
isDone
- the predicate to evaluate completed subtasks- Returns:
- a new Joiner object that yields a stream of all subtasks when all
subtasks complete or a predicate returns
true
to cancel the scope
-
Joiner
when preview features are enabled.