Structured Concurrency
We explored how virtual threads enable lightweight, high-scale concurrency with traditional blocking logic. Now, we introduce structured concurrency, a powerful model that brings clarity, safety, and predictability to multithreaded programming in Java.
What Is Structured Concurrency?
Structured concurrency is a programming model that treats multiple concurrent tasks running in a method as part of a single unit of work. All child threads must complete (or be canceled) before the parent scope exits. This ensures threads are well-scoped, making the code easier to reason about, debug, and manage.
Think of it as structured control flow for threads — just like try-with-resources
manages resource lifecycles, structured concurrency manages the lifecycle of spawned threads.
Java 21’s API: StructuredTaskScope
Java 21 introduces StructuredTaskScope
in java.util.concurrent
. It provides a way to spawn concurrent subtasks, wait for them to complete, and cancel others on success or failure.
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
Future<String> user = scope.fork(() -> fetchUser());
Future<String> order = scope.fork(() -> fetchOrder());
scope.join(); // Wait for all subtasks
scope.throwIfFailed(); // Propagate exceptions
return user.result() + " - " + order.result();
}
This model ensures both fetchUser()
and fetchOrder()
complete within the method’s scope. If one fails, the other is canceled automatically.
StructuredTaskScope Variants
Java provides three built-in variants:
StructuredTaskScope.ShutdownOnSuccess
— cancels remaining tasks when any subtask succeedsStructuredTaskScope.ShutdownOnFailure
— cancels all tasks when one fails (for fault tolerance)StructuredTaskScope
(manual join, no auto shutdown)
These offer granular control over what should happen when subtasks succeed or fail.
Benefits of Structured Concurrency
- Automatic cancellation of unused tasks
- Exception propagation from subtasks to parent
- Scoped lifetimes – no forgotten threads running in the background
- Better observability – threads appear nested and scoped in traces
Best Practices
- Use
StructuredTaskScope
for request-scoped parallelism - Prefer
ShutdownOnFailure
for fail-fast logic - Don’t leak tasks outside the scope
- Combine with virtual threads for low-cost task spawning
What’s Next?
Structured concurrency is one of the cleanest additions to Java’s concurrent toolkit in years. Next, we’ll explore ScopedValue
, Java's alternative to thread-local variables, optimized for virtual threads and structured concurrency.
No comments:
Post a Comment