Understanding Structured Concurrency (Java 21+)

1. Using StructuredTaskScope API

ClassUse
StructuredTaskScopeGeneric base
ShutdownOnFailureCancel siblings on first failure
ShutdownOnSuccessCancel siblings on first success
AutoCloseableUse in try-with-resources

Example: Parallel fetch

try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
    var user = scope.fork(() -> userSvc.find(id));
    var orders = scope.fork(() -> orderSvc.list(id));
    scope.join().throwIfFailed();
    return new Profile(user.get(), orders.get());
}

2. Creating Scoped Tasks

MethodReturns
scope.fork(Callable)Subtask handle
handle.get()Result after join
handle.state()RUNNING/SUCCESS/FAILED

3. Handling Task Failures

ApproachEffect
ShutdownOnFailure + throwIfFailedRe-throws first error
Inspect handlesIterate, check state
Custom scopeOverride handleComplete

4. Using ShutdownOnFailure Policy

APIUse
scope.join()Wait for completion or shutdown
scope.joinUntil(deadline)Bounded wait
throwIfFailed([fn])Throw if any subtask failed

5. Using ShutdownOnSuccess Policy

APIUse
result()First successful value
Use caseRace multiple replicas
FailureThrows if all subtasks failed

6. Understanding Scope Lifecycle

PhaseAction
Createtry-with-resources
ForkSpawn subtasks (must be on owner thread)
JoinBlock for all or shutdown
CloseAuto via try-with-resources

7. Propagating Errors and Cancellation

MechanismDetail
ShutdownInterrupts unfinished subtasks
Caller interruptPropagates to scope's subtasks
Re-throwthrowIfFailed wraps cause

8. Combining with Virtual Threads

AspectDetail
Default factoryStructuredTaskScope uses VTs
Custom factoryPass to constructor
ResultMassively concurrent, structured

9. Implementing Custom Task Scopes

OverridePurpose
handleComplete(Subtask)Custom completion logic
AggregationCollect all results
QuorumWait for K of N successes

Example: Collect-all scope

class CollectingScope<T> extends StructuredTaskScope<T> {
    final List<T> results = Collections.synchronizedList(new ArrayList<>());
    protected void handleComplete(Subtask<? extends T> s) {
        if (s.state() == Subtask.State.SUCCESS) results.add(s.get());
    }
}

10. Understanding Deadline Propagation

APIUse
joinUntil(Instant)Hard deadline
Sub-scopeInherit / shorten deadline
Timeout exceptionTimeoutException on overrun