Structured Concurrency in Java 21
Structured Concurrency (JEP 453) is a Preview feature in Java 21 that aims to simplify multithreaded programming. It treats multiple tasks running in different threads as a single unit of work.
The “Unstructured” Problem
Traditionally, when you spawn threads (using ExecutorService), they run independently.
- If the main thread fails, the sub-threads might keep running (leaking resources).
- If one sub-thread fails, the others don’t know about it and might continue uselessly.
- Debugging is hard because the stack traces are disconnected.
This “fire and forget” style is unstructured, much like goto statements were for invalid control flow.
The Structured Solution
Structured Concurrency introduces StructuredTaskScope. It ensures that when a scope exits, all its child threads are finished (either completed or cancelled).
Example: Fetching a User and their Orders
Imagine you need to fetch a User and their Orders from a database. These are two independent tasks that can run in parallel.
import java.util.concurrent.StructuredTaskScope;
import java.util.concurrent.ExecutionException;
Response handle() throws ExecutionException, InterruptedException {
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
// Fork two parallel tasks
var userTask = scope.fork(() -> findUser());
var orderTask = scope.fork(() -> fetchOrders());
// Wait for BOTH to finish.
// If EITHER fails, the other is cancelled automatically.
scope.join();
// If we get here, both succeeded (or we throw the exception)
scope.throwIfFailed();
// Combine the results
return new Response(userTask.get(), orderTask.get());
}
}
Key Benefits
- Error Handling: In the example above, if
findUser()throws an exception,fetchOrders()is automatically cancelled. You don’t waste resources fetching orders for a user that doesn’t exist. - Clean Code: The code reads top-to-bottom, like single-threaded code. The
try-with-resourcesblock guarantees cleanup. - Observability: Tools can link the threads together, making thread dumps and stack traces much easier to understand.
Structured Concurrency is the perfect companion to Virtual Threads, allowing you to manage thousands of concurrent tasks with sanity and safety.