• Home
  • About
    • Thoughts To Pen photo

      Thoughts To Pen

      My thoughts on Computer Programming || Psychology || Personal Finances || & much more...

    • Learn More
    • Twitter
    • Instagram
    • Github
    • StackOverflow
  • Posts
    • All Posts
    • All Tags
  • Projects
  • Portfolio
  • Resources
  • About

Structured Concurrency (Java 21)

27 Oct 2023

Structured Concurrency in Java 21

Structured Concurrency (JEP 453) is a Preview feature in Java 21 that aims to simplify multithreaded programming. It treats multiple tasks running in different threads as a single unit of work.

The “Unstructured” Problem

Traditionally, when you spawn threads (using ExecutorService), they run independently.

  • If the main thread fails, the sub-threads might keep running (leaking resources).
  • If one sub-thread fails, the others don’t know about it and might continue uselessly.
  • Debugging is hard because the stack traces are disconnected.

This “fire and forget” style is unstructured, much like goto statements were for invalid control flow.

The Structured Solution

Structured Concurrency introduces StructuredTaskScope. It ensures that when a scope exits, all its child threads are finished (either completed or cancelled).

Example: Fetching a User and their Orders

Imagine you need to fetch a User and their Orders from a database. These are two independent tasks that can run in parallel.

import java.util.concurrent.StructuredTaskScope;
import java.util.concurrent.ExecutionException;

Response handle() throws ExecutionException, InterruptedException {
    try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
        
        // Fork two parallel tasks
        var userTask  = scope.fork(() -> findUser());
        var orderTask = scope.fork(() -> fetchOrders());

        // Wait for BOTH to finish. 
        // If EITHER fails, the other is cancelled automatically.
        scope.join(); 
        
        // If we get here, both succeeded (or we throw the exception)
        scope.throwIfFailed();

        // Combine the results
        return new Response(userTask.get(), orderTask.get());
    }
}

Key Benefits

  1. Error Handling: In the example above, if findUser() throws an exception, fetchOrders() is automatically cancelled. You don’t waste resources fetching orders for a user that doesn’t exist.
  2. Clean Code: The code reads top-to-bottom, like single-threaded code. The try-with-resources block guarantees cleanup.
  3. Observability: Tools can link the threads together, making thread dumps and stack traces much easier to understand.

Structured Concurrency is the perfect companion to Virtual Threads, allowing you to manage thousands of concurrent tasks with sanity and safety.



programmingjavajava21 Share Tweet Msg