Site Search:

Structured Concurrency

Back> 

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 succeeds
  • StructuredTaskScope.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