Structured concurrency (preview)
Treat concurrent subtasks like a block of code: they start together, fail together and end together.
Open this lesson in the learning hubKey points
- Loose
submit()calls leak. When one task fails, its siblings keep running with nobody watching them. StructuredTaskScopeties subtasks to a block, so nothing you fork can outlive the try-with-resources.ShutdownOnFailurecancels the remaining subtasks as soon as one fails, thenthrowIfFailedrethrows.ShutdownOnSuccessis the opposite race: keep the first answer that arrives and cancel the rest.- The stack trace keeps the parent-child relation, so a failure reads like an ordinary nested call.
- It is a preview API in Java 21, so it needs
--enable-previewto compile and run.
Example
import java.util.concurrent.StructuredTaskScope; // Java 21 preview: run with --enable-preview
public class Main {
record User(String name) { }
record Order(int count) { }
public static void main(String[] args) throws Exception {
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
StructuredTaskScope.Subtask<User> user = scope.fork(() -> new User("ada"));
StructuredTaskScope.Subtask<Order> order = scope.fork(() -> new Order(3));
scope.join(); // wait for both children
scope.throwIfFailed(); // if either failed, the other was already cancelled
System.out.println(user.get().name() + " has " + order.get().count() + " orders");
} // close() guarantees no child outlives this block
}
}
Subtasks should live and die inside the block that started them.
This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Multithreading course, and every lesson in it is listed on the Multithreading contents page.