Structured concurrency (preview)
Treat a group of concurrent subtasks as one unit that succeeds or fails together.
Open this lesson in the learning hubKey points
- Fire two
Futures and one fails: the other keeps running, and nobody cancels it. StructuredTaskScopeties subtask lifetimes to a block - leave the block, they are all done or cancelled.ShutdownOnFailurecancels the siblings the moment one subtask throws.- It also fixes observability: the subtasks appear as children of the caller in a thread dump.
- Preview in 21, so it needs
--enable-previewand the API is still moving.
Example
// Preview API in Java 21 - requires --enable-preview to compile and run.
import java.util.concurrent.*; // in 21 StructuredTaskScope lives here, not jdk.incubator
public class Main {
record Weather(String city, int degrees) { }
public static void main(String[] args) throws Exception {
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
// fork() hands back a Subtask, not a Future - the scope owns the lifetime.
StructuredTaskScope.Subtask<String> user = scope.fork(() -> "ada");
StructuredTaskScope.Subtask<Weather> weather = scope.fork(() -> new Weather("London", 14));
scope.join(); // wait for both
scope.throwIfFailed(); // rethrow the first failure
System.out.println(user.get() + " sees " + weather.get());
}
// Leaving the block guarantees no subtask is still running.
}
}
Structured concurrency makes a group of subtasks behave like a block - they all end when it does.
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 Java 21 Course course, and every lesson in it is listed on the Java 21 Course contents page.