Interface StructuredTaskScope.Joiner<T, R, R_X extends Throwable>
- Type Parameters:
T- the result type of subtasks forkedPREVIEW in the scopeR- the type of the result returned by thejoin()PREVIEW methodR_X- the type of the exception thrown by thejoin()PREVIEW method
- Enclosing interface:
StructuredTaskScopePREVIEW<T, R, R_X extends Throwable>
public static interface StructuredTaskScope.Joiner<T, R, R_X extends Throwable>
Joiner is a preview API of the Java platform. StructuredTaskScopePREVIEW to produce the outcome for the scope's join()PREVIEW method. A StructuredTaskScope is opened with a Joiner that handles subtasks as they are forkedPREVIEW in the scope and again when they complete execution. The Joiner handles subtasks that complete successfully with a result of type T, or fail with any exception or error. The Joiner implements a policy that may cancel the scope when some condition is reached (for example, a subtask fails). When all subtasks complete execution, or the scope is cancelled, the Joiner produces the outcome for the join()PREVIEW method. The outcome is a result of type R or an exception of type R_X.
Joiner defines static methods to create Joiner objects for common cases:
-
allSuccessfulOrThrow()andallSuccessfulOrThrow(Function)create aJoinerthat produces a list of all results forjoin()to return when all subtasks complete successfully. TheJoinercancels the scope and causesjoin()to throwExecutionException, or an exception returned by an exception supplying function, if any subtask fails. -
anySuccessfulOrThrow()andanySuccessfulOrThrow(Function)create aJoinerthat produces the result of any successful subtask forjoin()to return. TheJoinercausesjoin()to throwExecutionException, or an exception returned by an exception supplying function, if all subtasks fail. -
awaitAllSuccessfulOrThrow()andawaitAllSuccessfulOrThrow(Function)create aJoinerthat waits for all subtasks to complete successfully. TheJoinerdoes not produce a non-nullresult forjoin()to return. TheJoinercancels the scope and causesjoin()to throwExecutionException, or an exception returned by an exception supplying function, if any subtask fails.
In addition to the methods to create Joiner objects for common cases, the allUntil(Predicate) method can be used to create a Joiner that implements a cancellation policy. The Joiner is created with a predicate that is evaluated on completed subtasks. The Joiner cancels the scope if the predicate evaluates to true. When using this Joiner, the outcome of the join() method is the list of all subtasks forked in the scope.
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 whether the 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 outcome (result or exception) for the
join() method. The timeout() method must be implemented to produce the outcome for the timeoutPREVIEW case.
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
Joinerobject is created for eachStructuredTaskScope.Joinerobjects should never be shared with different scopes or re-used after a scope is closed. - Implementation Requirements:
- Implementations of this interface must be thread-safe. The
onComplete(Subtask)method may be invoked concurrently as multiple subtasks can complete at the same time. Additionally, theonComplete(Subtask)method may be called concurrently with the scope owner thread invoking theonFork(Subtask),result(), ortimeout()methods.A
Joinershould clearly document how it handles timeoutsPREVIEW. In many cases, a timeout will cause thejoin()method to throw an exception withCancelledByTimeoutExceptionPREVIEW as the cause. SomeJoinerimplementation may be capable of returning a result for the timeout case.Designing a
Joinershould take into account the code at the use-site where the results from thejoin()PREVIEW method are processed. It should be clear what theJoinerdoes vs. the application code at the use-site. In general, theJoinerimplementation is not the place for "business logic". AJoinershould be designed to be as general purpose as possible. - Since:
- 25
- See Also:
Method Summary
| Modifier and Type | Method | Description |
|---|---|---|
static <T> StructuredTaskScope.JoinerPREVIEW |
allSuccessfulOrThrow() |
Returns a new Joiner that produces a list of all results when all subtasks complete successfully. |
static <T, R_X extends Throwable> |
allSuccessfulOrThrow |
Returns a new Joiner that produces a list of all results when all subtasks complete successfully. |
static <T> StructuredTaskScope.JoinerPREVIEW |
allUntil |
Returns a new Joiner that produces a list of all subtasks when all subtasks complete or evaluating a predicate on a completed subtask causes the scope to be cancelled. |
static <T> StructuredTaskScope.JoinerPREVIEW |
anySuccessfulOrThrow() |
Returns a new Joiner that produces the result of any successful subtask. |
static <T, R_X extends Throwable> |
anySuccessfulOrThrow |
Returns a new Joiner that produces the result of any successful subtask. |
static <T> StructuredTaskScope.JoinerPREVIEW |
awaitAllSuccessfulOrThrow() |
|
static <T, R_X extends Throwable> |
awaitAllSuccessfulOrThrow |
|
default boolean |
onComplete |
Invoked by the thread that executed a subtask after the subtask completes successfully or fails with an exception. |
default boolean |
onFork |
|
R |
result() |
|
R |
timeout() |
Method Details
onFork
default boolean onFork(StructuredTaskScope.SubtaskPREVIEW<T> subtask)
fork(Callable)PREVIEW and fork(Runnable)PREVIEW when forking a subtask. The method is invoked before a thread is created to execute the subtask.- API Note:
- This method is invoked by the
forkmethods. It should not be invoked directly. - Implementation Requirements:
- The default implementation throws
NullPointerExceptionif the subtask isnull. It throwsIllegalArgumentExceptionif the subtask is not in theUNAVAILABLEPREVIEW state, it otherwise returnsfalse. - Parameters:
-
subtask- the subtask - Returns:
-
trueto cancel the scope, otherwisefalse
onComplete
default boolean onComplete(StructuredTaskScope.SubtaskPREVIEW<T> subtask)
- API Note:
- This method is invoked by subtasks when they complete. It should not be invoked directly.
- Implementation Requirements:
- The default implementation throws
NullPointerExceptionif the subtask isnull. It throwsIllegalArgumentExceptionif the subtask is not in theSUCCESSPREVIEW orFAILEDPREVIEW state, it otherwise returnsfalse. - Parameters:
-
subtask- the subtask - Returns:
-
trueto cancel the scope, otherwisefalse
result
R result() throws R_X
join()PREVIEW method to produce the outcome (result or exception) after waiting for all subtasks to complete or the scope is cancelled. This method is not invoked if the scope was opened with a timeout and the timeout expires before or while waiting. This method will be called at most once, by the join() method, to produce the outcome. The behavior of this method when invoked directly is undefined.
- API Note:
- This method is invoked by the
join()method. It should not be invoked directly. - Returns:
- the result
- Throws:
-
R_X- if the outcome is an exception
timeout
R timeout() throws R_X
join()PREVIEW method to produce the outcome (result or exception) when the scope was opened with a timeout and the timeout expires before or while waiting in the join() method. If the outcome is an exception, this method throws the exception with a CancelledByTimeoutExceptionPREVIEW as the cause.
This method will be called at most once, by the join() method, to produce the outcome. The behavior of this method when invoked directly is undefined.
- API Note:
- This method is invoked by the
join()method. It should not be invoked directly. - Returns:
- the result
- Throws:
-
R_X- with a cause ofCancelledByTimeoutException, if the outcome is an exception - Since:
- 27
allSuccessfulOrThrow
static <T, R_X extends Throwable> StructuredTaskScope.JoinerPREVIEW<T,List<T>,R_X> allSuccessfulOrThrow(Function<Throwable, R_X> esf)
Joiner cancels the scope and causes the join()PREVIEW method to throw if any subtask fails. The join()PREVIEW method of a StructuredTaskScopePREVIEW opened with this Joiner returns the list of the results, in the order that the subtasks were forkedPREVIEW, when all subtasks complete successfully. An empty list is returned if no subtasks were forked. If any subtask fails then the Joiner causes the join() method to throw the exception returned by the given exception supplying function when applied to the exception from the first subtask to fail. The function should return an exception with the exception from the failed subtask (the function argument) as the cause. If the function returns null then it causes the join() method to throw NullPointerException.
Timeout Handling: The Joiner cannot produce a result when the scope is cancelled by a timeout. If the scope was opened with a timeoutPREVIEW, and the timeout expires before or while waiting for all subtasks to complete successfully, then the Joiner causes the join() method to throw the exception returned by the exception supplying function when applied to a CancelledByTimeoutExceptionPREVIEW.
- API Note:
- Joiners returned by this method are suited to cases where all subtasks return a result of the same type. It removes the need for bookkeeping and the need to keep a reference to the
SubtaskPREVIEW objects returned by thefork(Callable)PREVIEW method. Joiners returned byawaitAllSuccessfulOrThrow(Function)andawaitAllSuccessfulOrThrow()are suited to cases where the subtasks return results of different types and where it is necessary to keep a reference to theSubtaskobjects.The following example is a method that opens a
StructuredTaskScopewith a Joiner created withallSuccessfulOrThrow(Function). The method is invoked with a collection of callables. It forksPREVIEW a subtask to execute each callable, waits injoin()PREVIEW for all subtasks to complete successfully, and then returns a list of the results. It throws the runtime exceptionCompletionExceptionif any subtask fails, with the exception from the first subtask to fail as the cause.<T> List<T> invokeAll(Collection<Callable<T>> tasks) throws InterruptedException { try (var scope = StructuredTaskScope.open( Joiner.<T, CompletionException>allSuccessfulOrThrow(CompletionException::new))) { tasks.forEach(scope::fork); List<T> results = scope.join(); return results; } } - Type Parameters:
T- the result type of subtasksR_X- the type of the exception thrown by thejoin()PREVIEW method- Parameters:
-
esf- the exception supplying function - Returns:
- a new Joiner that produces a list of all results when all subtasks complete successfully
- Since:
- 27
- See Also:
allSuccessfulOrThrow
static <T> StructuredTaskScope.JoinerPREVIEW<T, List<T>, ExecutionException> allSuccessfulOrThrow()
Joiner cancels the scope and causes the join()PREVIEW method to throw ExecutionException if any subtask fails. The join()PREVIEW method of a StructuredTaskScopePREVIEW opened with this Joiner returns the list of the results, in the order that the subtasks were forkedPREVIEW, when all subtasks complete successfully. An empty list is returned if no subtasks were forked. If any subtask fails then the Joiner causes the join() method to throw ExecutionException with the exception from the first subtask to fail as the cause.
Timeout Handling: The Joiner cannot produce a result when the scope is cancelled by a timeout. If the scope was opened with a timeoutPREVIEW, and the timeout expires before or while waiting for all subtasks to complete successfully, then the Joiner causes the join() method to throw ExecutionException with a CancelledByTimeoutExceptionPREVIEW as the cause.
- Implementation Requirements:
- A Joiner returned by this method is equivalent to invoking
allSuccessfulOrThrow(ExecutionException::new). - Type Parameters:
T- the result type of subtasks- Returns:
- a new Joiner that produces a list of all results when all subtasks complete successfully
anySuccessfulOrThrow
static <T, R_X extends Throwable> StructuredTaskScope.JoinerPREVIEW<T,T,R_X> anySuccessfulOrThrow(Function<Throwable, R_X> esf)
Joiner cancels the scope when a subtask completes successfully. It causes the join()PREVIEW method to throw if all subtasks fail. The join()PREVIEW method of a StructuredTaskScopePREVIEW opened with this Joiner returns the result of a successful subtask. If a subtask completes successfully then the scope is cancelled and the join() method returns its result. If all subtasks fail then the Joiner causes the join() method to throw the exception returned by the given exception supplying function when applied to the exception from one of the failed subtasks. The function should return an exception with the exception from the failed subtask (the function argument) as the cause. If the function returns null then it causes the join() method to throw NullPointerException. If no subtasks were forked then the Joiner causes the join() method to throw the exception returned by the function when applied to an instance of NoSuchElementException.
Timeout Handling: The Joiner cannot produce a result when the scope is cancelled by a timeout. If the scope was opened with a timeoutPREVIEW, and the timeout expires before or while waiting for a subtask to complete successfully, then the Joiner causes the join() method to throw the exception returned by the exception supplying function when applied to a CancelledByTimeoutExceptionPREVIEW.
- API Note:
- The following example is a method that opens a
StructuredTaskScopewith a Joiner created withanySuccessfulOrThrow(Function). The method is invoked with a collection of callables. It forksPREVIEW a subtask to execute each callable, waits injoin()PREVIEW for any subtask to complete successfully, returning its result. It throws the runtime exceptionCompletionExceptionif all subtasks fail, with the exception from a failed subtask as the cause.<T> T invokeAny(Collection<Callable<T>> tasks) throws InterruptedException { try (var scope = StructuredTaskScope.open( Joiner.<T, CompletionException>anySuccessfulOrThrow(CompletionException::new))) { tasks.forEach(scope::fork); T result = scope.join(); return result; } } - Type Parameters:
T- the result type of subtasksR_X- the type of the exception thrown by thejoin()PREVIEW method- Parameters:
-
esf- the exception supplying function - Returns:
- a new Joiner that produces the result of any successful subtask
- Since:
- 27
- See Also:
anySuccessfulOrThrow
static <T> StructuredTaskScope.JoinerPREVIEW<T, T, ExecutionException> anySuccessfulOrThrow()
Joiner cancels the scope when a subtask completes successfully. It causes the join()PREVIEW method to throw ExecutionException if all subtasks fail. The join()PREVIEW method of a StructuredTaskScopePREVIEW opened with this Joiner returns the result of a successful subtask. If a subtask completes successfully then the scope is cancelled and the join() method returns its result. If all subtasks fail then the Joiner causes the
join() method to throw ExecutionException with the exception from one of the failed subtasks as the cause. If no subtasks were forked then the Joiner causes the join() method to throw ExecutionException with NoSuchElementException as the cause.
Timeout Handling: The Joiner cannot produce a result when the scope is cancelled by a timeout. If the scope was opened with a timeoutPREVIEW, and the timeout expires before or while waiting for a subtask to complete successfully, then the Joiner causes the join() method to throw ExecutionException with a CancelledByTimeoutExceptionPREVIEW as the cause.
- Implementation Requirements:
- A Joiner returned by this method is equivalent to invoking
anySuccessfulOrThrow(ExecutionException::new). - Type Parameters:
T- the result type of subtasks- Returns:
- a new Joiner that produces the result of any successful subtask
- Since:
- 26
awaitAllSuccessfulOrThrow
static <T, R_X extends Throwable> StructuredTaskScope.JoinerPREVIEW<T,Void,R_X> awaitAllSuccessfulOrThrow(Function<Throwable, R_X> esf)
join()PREVIEW method to wait for all subtasks to complete successfully. The Joiner cancels the scope and causes the join()PREVIEW method to throw if any subtask fails. The join()PREVIEW method of a StructuredTaskScopePREVIEW opened with this Joiner returns null when all subtasks complete successfully. If any subtask fails then the Joiner causes the join() method to throw the exception returned by the given exception supplying function when applied to the exception from the first subtask to fail. The function should return an exception with the exception from the failed subtask (the function argument) as the cause. If the function returns null then it causes the join() method to throw NullPointerException.
Timeout Handling: The Joiner cannot produce a result when the scope is cancelled by a timeout. If the scope was opened with a timeoutPREVIEW, and the timeout expires before or while waiting for all subtasks to complete successfully, then the Joiner causes the join() method to throw the exception returned by the exception supplying function when applied to a CancelledByTimeoutExceptionPREVIEW.
- API Note:
- Joiners returned by this method are suited to cases where subtasks return results of different types and where it is necessary to keep a reference to each
SubtaskPREVIEW. Joiners returned byallSuccessfulOrThrow(Function)andallSuccessfulOrThrow()are suited to cases where the subtasks return a result of the same type.The following example opens a
StructuredTaskScopewith a Joiner created withawaitAllSuccessfulOrThrow(). It forksPREVIEW two subtasks, then waits injoin()PREVIEW for both subtasks to complete successfully or either subtask to fail. If both subtasks complete successfully then it invokesSubtask.get()PREVIEW on both subtasks to get their results. It throws the runtime exceptionCompletionExceptionif any subtask fails, with the exception from a failed subtask as the cause.try (var scope = StructuredTaskScope.open( Joiner.awaitAllSuccessfulOrThrow(CompletionException::new))) { Subtask<String> subtask1 = scope.fork(callable1); Subtask<Integer> subtask2 = scope.fork(callable2); // throws CompletionException if either subtask fails scope.join(); // both subtasks completed successfully var result = new MyResult(subtask1.get(), subtask2.get()); } - Type Parameters:
T- the result type of subtasksR_X- the type of the exception thrown by thejoin()PREVIEW method- Parameters:
-
esf- the exception supplying function - Returns:
- a new Joiner that causes the
join()PREVIEW method to wait for all subtasks to complete successfully - Since:
- 27
awaitAllSuccessfulOrThrow
static <T> StructuredTaskScope.JoinerPREVIEW<T, Void, ExecutionException> awaitAllSuccessfulOrThrow()
join()PREVIEW method to wait for all subtasks to complete successfully. The Joiner cancels the scope and causes the join()PREVIEW method to throw ExecutionException if any subtask fails. The join()PREVIEW method of a StructuredTaskScopePREVIEW opened with this Joiner returns null when all subtasks complete successfully. If any subtask fails then the Joiner causes the join() method to throw ExecutionException with the exception from the first subtask to fail as the cause.
Timeout Handling: The Joiner cannot produce a result when the scope is cancelled by a timeout. If the scope was opened with a timeoutPREVIEW, and the timeout expires before or while waiting for all subtasks to complete successfully, then the Joiner causes the join() method to throw ExecutionException with a CancelledByTimeoutExceptionPREVIEW as the cause.
- Implementation Requirements:
- A Joiner returned by this method is equivalent to invoking
awaitAllSuccessfulOrThrow(ExecutionException::new). - Type Parameters:
T- the result type of subtasks- Returns:
- a new Joiner that causes the
join()PREVIEW method to wait for all subtasks to complete successfully - See Also:
allUntil
static <T> StructuredTaskScope.JoinerPREVIEW<T, List<StructuredTaskScope.SubtaskPREVIEW<T>>, RuntimeException> allUntil(Predicate<? super StructuredTaskScope.SubtaskPREVIEW<T>> isDone)
Joiner does not cause the join()PREVIEW method to throw if subtasks fail or a configured timeoutPREVIEW expires. This method can be used to create a Joiner that implements a cancellation policy. The join()PREVIEW method of a StructuredTaskScopePREVIEW opened with this Joiner returns a list of all subtasks, in the order that they were forkedPREVIEW, when all subtasks complete or the scope is cancelled. The returned list may contain subtasks that completed (in the SUCCESSPREVIEW or FAILEDPREVIEW state), or subtasks in the UNAVAILABLEPREVIEW state if they were forked or completed after the scope was cancelled. The scope is cancelled if the given predicate evaluates to true, or a configured timeout expires before or while waiting in the join() method.
The given Predicate's test(Object) method is invoked on a completed subtask by the thread that executed the subtask. The method is invoked after the subtask completes (successfully or with an exception) before the thread terminates. The scope is cancelled if the
test method returns true. The test method must be thread safe. It may be invoked concurrently from several threads as multiple subtasks can complete at the same time. If the method throws an exception or error, the thread invokes the uncaught exception handler with the exception or error before the thread terminates.
Timeout Handling: If used with a scope that has a timeoutPREVIEW set, and the timeout expires before all subtasks complete then the join() method returns the list of all subtasks. It does not throw an exception. Subtasks that did not complete before the timeout expires will be in the UNAVAILABLE state.
- API Note:
- The following example uses
allUntilto create a Joiner that cancels the scope when two or more subtasks fail.class CancelAfterTwoFailures implements Predicate<Subtask<?>> { private final AtomicInteger failedCount = new AtomicInteger(); @Override public boolean test(Subtask<?> subtask) { return subtask.state() == Subtask.State.FAILED && failedCount.incrementAndGet() >= 2; } } var joiner = Joiner.<String>allUntil(new CancelAfterTwoFailures());The following example uses
allUntilto create a Joiner that cancels the scope when any subtask completes successfully. The subtasks are grouped according to their state to produce a map with up to three key-value mappings. The map key is the subtask state, the value is the list of subtasks in that state.Predicate<Subtask<?>> isSuccessful = s -> s.state() == Subtask.State.SUCCESS; try (var scope = StructuredTaskScope.open(Joiner.<String>allUntil(isSuccessful))) { tasks.forEach(scope::fork); Map<Subtask.State, List<Subtask<String>>> subtasksByState = scope.join() .stream() .collect(Collectors.groupingBy(Subtask::state)); }The following example is a method that uses
allUntilto create a Joiner that does not cancel the scope. The method waits for all subtasks to complete or a timeout to expire. It returns a list of all subtasks, in the same order as the collection of callables, even if the timeout expires before or while waiting injoin().<T> List<Subtask<T>> invokeAll(Collection<Callable<T>> tasks, Duration timeout) throws InterruptedException { try (var scope = StructuredTaskScope.open(Joiner.<T>allUntil(_ -> false), cf -> cf.withTimeout(timeout))) { tasks.forEach(scope::fork); return scope.join(); } } - Type Parameters:
T- the result type of subtasks- Parameters:
-
isDone- the predicate to evaluate completed subtasks - Returns:
- a new Joiner that produces a list of all subtasks when all subtasks complete or evaluating a predicate on a completed subtask causes the scope to be cancelled
© 1993, 2025, Oracle and/or its affiliates. All rights reserved.
Documentation extracted from Debian's OpenJDK Development Kit package.
Licensed under the GNU General Public License, version 2, with the Classpath Exception.
Various third party code in OpenJDK is licensed under different licenses (see Debian package).
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
Joinerwhen preview features are enabled.