Java Structured Concurrency
In this page:
What is Structured Concurrency?
Structured concurrency, previewed alongside virtual threads, treats a group of related concurrent subtasks as a single unit that starts and finishes together, replacing ad-hoc thread management with a scope that has a clear, predictable lifetime.
Example: What is Structured Concurrency?
public class Main {
public static void main(String[] args) {
System.out.println("Related subtasks start and finish together as one unit");
}
}
Login to try C/C++/Java/PHP code in the editor
StructuredTaskScope Basics
A StructuredTaskScope is opened in a try-with-resources block, and its fork method starts a subtask on its own virtual thread, while join blocks until every forked subtask in that scope has completed.
Example: StructuredTaskScope Basics
import java.util.concurrent.StructuredTaskScope;
public class Main {
public static void main(String[] args) throws Exception {
try (var scope = new StructuredTaskScope<String>()) {
scope.fork(() -> "subtask result"); // runs on its own virtual thread
scope.join(); // blocks until every forked subtask completes
System.out.println("All subtasks finished");
}
}
}
Login to try C/C++/Java/PHP code in the editor
Forking Subtasks
Multiple related subtasks, such as fetching different pieces of data needed for the same response, can be forked within one scope so they run concurrently, and each returns a Subtask handle used to retrieve its result later.
Example: Forking Subtasks
import java.util.concurrent.StructuredTaskScope;
public class Main {
public static void main(String[] args) throws Exception {
try (var scope = new StructuredTaskScope<Integer>()) {
var task1 = scope.fork(() -> 10);
var task2 = scope.fork(() -> 20); // both run concurrently
scope.join();
System.out.println(task1.get() + task2.get());
}
}
}
Login to try C/C++/Java/PHP code in the editor
Joining and Handling Results
After join returns, every subtask's outcome is available: get() retrieves a successful result, and specialized scopes like ShutdownOnSuccess let the whole operation finish as soon as the first subtask succeeds, cancelling the rest.
Example: Joining and Handling Results
import java.util.concurrent.StructuredTaskScope;
public class Main {
public static void main(String[] args) throws Exception {
try (var scope = new StructuredTaskScope.ShutdownOnSuccess<Integer>()) {
scope.fork(() -> 1);
scope.fork(() -> 2);
scope.join();
System.out.println("First success: " + scope.result()); // finishes on first success, cancels the rest
}
}
}
Login to try C/C++/Java/PHP code in the editor
Error Propagation
ShutdownOnFailure cancels every other subtask in the scope as soon as any one of them fails, and throwIfFailed re-raises that failure back on the thread that owns the scope, giving structured, predictable error handling across concurrent subtasks.
Example: Error Propagation
import java.util.concurrent.StructuredTaskScope;
public class Main {
public static void main(String[] args) throws Exception {
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
scope.fork(() -> { throw new RuntimeException("subtask failed"); });
scope.join();
scope.throwIfFailed(); // re-raises the failure on the owning thread
} catch (Exception e) {
System.out.println("Caught: " + e.getCause().getMessage());
}
}
}
Login to try C/C++/Java/PHP code in the editor
Chapter Quiz — Complete all 12 topics to unlock
0/12 topics done
Complete these topics first: