Skip to main content
  1. Java Concurrency (java.util.concurrent)/

Structured Concurrency (Loom)

2 mins

StructuredTaskScope is a modern Java concurrency API introduced in Java 19 (as an incubator) and refined in subsequent releases. It aims to make concurrent code safer, easier to debug, and more similar to synchronous code.

Source Code #

View Source on GitHub

The “Joiner” Logic #

Structured Concurrency treats multiple tasks as a single unit of work. When you use StructuredTaskScope, you create a scope and then fork tasks within it. When the scope is closed, all tasks are guaranteed to have finished (succeeded, failed, or cancelled).

try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
    Supplier<String> user  = scope.fork(() -> userService.getUser(id));
    Supplier<Integer> order = scope.fork(() -> orderService.getOrder(id));

    scope.join();           // Join both forks
    scope.throwIfFailed();  // Propagate errors from either fork

    // Use the results
    return new UserOrder(user.get(), order.get());
}

Canonical Usage #

When to use: Use StructuredTaskScope in modern Java (19+) whenever you have a “fan-out” pattern (starting multiple subtasks and waiting for their results). It is especially powerful when used with Virtual Threads.

Common Patterns:

  • ShutdownOnFailure: The scope “short-circuits” and cancels all other tasks as soon as one fails.
  • ShutdownOnSuccess: The scope “short-circuits” and returns the first task to succeed, cancelling all others (the “race” pattern).

Advantages Over CompletableFuture #

  • Error Propagation: Errors are automatically collected and propagated. No more “unhandled” async exceptions.
  • Cancellation: If the main thread is interrupted, all tasks in the scope are automatically cancelled.
  • Debugging: Thread dumps show the logical hierarchy of parent and child tasks (structured), making it much easier to diagnose deadlocks or leaks.