Close Menu
Şevket Ayaksız

    Subscribe to Updates

    Get the latest creative news from FooBar about art, design and business.

    What's Hot

    Save 40% on GeForce Now’s Priority Tier Subscription

    Mayıs 22, 2025

    Experience Seamless Conversations with Google Meet’s Live AI Translations

    Mayıs 22, 2025

    Gmail’s Smart Reply gets a major AI boost

    Mayıs 22, 2025
    Facebook X (Twitter) Instagram
    • software
    • Gadgets
    Facebook X (Twitter) Instagram
    Şevket AyaksızŞevket Ayaksız
    Subscribe
    • Home
    • Technology

      Introducing AMD’s 96-Core Threadripper 9000 CPUs: A New Era in Computing

      Mayıs 22, 2025

      AMD’s Radeon RX 9060 XT Delivers Better Value Than Nvidia’s RTX 5060 Ti

      Mayıs 22, 2025

      MSI’s Claw A8 Introduces AMD-Powered Gaming Handheld

      Mayıs 22, 2025

      Score a BOGO Offer on Samsung Gaming Monitors Now

      Mayıs 22, 2025

      SwitchBot Hub 3 Now Available for Preorder at $119.99

      Mayıs 22, 2025
    • Adobe
    • Microsoft
    • java
    • Oracle
    Şevket Ayaksız
    Anasayfa » Unlocking Efficiency: A Guide to Embracing Java’s Cutting-Edge Structured Concurrency Model
    software

    Unlocking Efficiency: A Guide to Embracing Java’s Cutting-Edge Structured Concurrency Model

    By ayaksızAralık 15, 2023Yorum yapılmamış9 Mins Read
    Facebook Twitter Pinterest LinkedIn Tumblr Email
    Share
    Facebook Twitter LinkedIn Pinterest Email

    Unlocking the Future of Multithreading: Java’s Structured Concurrency Model

    Structured concurrency has emerged as a revolutionary approach to multithreading in Java, introducing a paradigm shift that enables developers to conceptualize work in logical groups. This innovative model, featured in the preview of Java 21, leverages both traditional and virtual threads, making it a crucial element in shaping the future of Java programming. Now is the opportune moment to delve into the realm of structured concurrency and harness its potential.

    The Imperative Need for Structured Concurrency

    Crafting concurrent software remains a formidable challenge for software developers, and Java’s thread model, while robust, has historically presented inherent complexities in multithreading. Structured concurrency addresses this challenge by allowing developers to employ multiple threads within the framework of structured programming syntax. Essentially, it offers a way to write concurrent software using familiar program flows and constructs, liberating developers from the intricacies of thread orchestration. As expressed in the JEP for structured concurrency, “If a task splits into concurrent subtasks then they all return to the same place, namely the task’s code block.”

    With the advent of virtual threads as an official feature in Java, the ability to spawn threads inexpensively for concurrent performance becomes a reality. Structured concurrency provides the straightforward syntax needed to capitalize on this capability. The outcome is a distinctive and highly optimized threading system in Java that remains easily comprehensible.

    Introducing the StructuredTaskScope Class

    At the core of structured concurrency lies the java.util.concurrent.StructuredTaskScope class. The Java 21 documentation showcases practical examples of integrating structured concurrency into programming workflows. To enable structured concurrency in Java programs, developers currently need to employ –enable-preview and –source 21 or –source 22. For instance, using Maven with openjdk 22-ea, the compile step specifies –enable-preview –source 22, while the execution step simply requires –enable-preview. (SDKMan is a recommended tool for managing multiple JDK installs.)

    For hands-on exploration, refer to the example code available in the accompanying GitHub repository for this article. Note the .mvn/jvm.config file, which sets –enable-preview for execution. Execute the code with $mvn clean compile exec:java to experience the power of structured concurrency in action.

    Multithreading with structured concurrency

    For our examples, we’ll make several requests to the Star Wars API (SWAPI) to get information about planets by their ID. If we were doing this in standard synchronous Java, we’d probably do something like Listing 1, using the Apache HTTPClient.

    Listing 1. Conventional-style multiple API calls

    
    package com.infoworld;
    
    import org.apache.http.client.methods.CloseableHttpResponse;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.util.EntityUtils;
    
    public class App {
      public String getPlanet(int planetId) throws Exception {
        System.out.println("BEGIN getPlanet()");
        String url = "https://swapi.dev/api/planets/" + planetId + "/";
        String ret = "?";
    
        CloseableHttpClient httpClient = HttpClients.createDefault();
     
        HttpGet request = new HttpGet(url);
        CloseableHttpResponse response = httpClient.execute(request);
    
        // Check the response status code
        if (response.getStatusLine().getStatusCode() != 200) {
          System.err.println("Error fetching planet information for ID: " + planetId);
          throw new RuntimeException("Error fetching planet information for ID: " + planetId);
        } else {
          // Parse the JSON response and extract planet information
            ret = EntityUtils.toString(response.getEntity());
            System.out.println("Got a Planet: " + ret);
          }
    
          // Close the HTTP response and client
          response.close();
          httpClient.close();
          return ret;
        }   
        void sync() throws Exception {
          int[] planetIds = {1,2,3,4,5};
          for (int planetId : planetIds) {
            getPlanet(planetId);
          }
        }
        public static void main(String[] args) {
            var myApp = new App();
            System.out.println("\n\r-- BEGIN Sync");
            try {
              myApp.sync();
            } catch (Exception e){
              System.err.println("Error: " + e);
            }
        }
    }

    In Listing 1, we have a main method that calls the sync() method, which simply iterates over a set of IDs while issuing calls to the "https://swapi.dev/api/planets/" + planetId endpoint. These calls are issued via the getPlanet() method, which uses the Apache HTTP library to handle the boilerplate request, response, and error handling. Essentially, the method receives each response and prints it to the console if it’s good (200); otherwise, it throws an error.

    The output is something like this:

    
    -- BEGIN Sync
    BEGIN getPlanet()
    Got a Planet: {"name":"Tatooine"} 
    BEGIN getPlanet()
    Got a Planet: {"name":"Alderaan"}
    BEGIN getPlanet()
    Got a Planet: {"name":"Yavin”}
    BEGIN getPlanet()
    Got a Planet: {"name":"Hoth"}
    BEGIN getPlanet()
    Got a Planet: {"name":"Dagobah"}

    Now let’s try the same example using structured concurrency. As shown in Listing 2, structured concurrency lets us break up the calls into concurrent requests and keep everything in the same code space. In Listing 2, we add the necessary StructuredTaskScope import, then use its core methods, fork() and join(), to break each request into its own thread and then wait on them all.

    Maximizing Efficiency with Concurrent Execution

    Executing the provided Listing 2 yields comparable results, but the structured concurrency showcased in this example significantly accelerates the process by issuing requests simultaneously. A noteworthy comparison arises between the sc() method, employing multithreading through structured concurrency, and the sync() method, which relies on synchronous code. The structured concurrency paradigm, while not substantially more complex to conceptualize, demonstrates a remarkable improvement in speed.

    Navigating the Task and Subtask Landscape

    In the realm of structured concurrency, the creation of a StructuredTaskScope initiates a workflow that leverages virtual threads by default. Unlike traditional multithreading approaches that allocate operating system threads, structured concurrency instructs the Java Virtual Machine (JVM) to efficiently orchestrate requests. It’s worth noting that the StructuredTaskScope constructor offers the flexibility to accept a ThreadFactory if needed.

    Listing 2 showcases the creation of a StructuredTaskScope object within a try-with-resource block, aligning with its intended usage. The fork() method becomes a pivotal tool, enabling developers to spawn as many jobs as required. This method is versatile, accepting anything implementing Callable, including methods or functions. Notably, the use of an anonymous function, such as () -> getPlanet(planetId), provides a concise syntax for passing arguments into the target function.

    Upon invoking join(), the structured concurrency model orchestrates the parallel tasks to synchronize, seamlessly transitioning back to synchronous mode. Crucially, the forked jobs adhere to the configurations set by the TaskScope.

    Graceful Termination of Task Scope

    The StructuredTaskScope, created within a try-with-resource block, automatically undergoes closure when the block concludes. This triggers the shutdown() process for the scope, offering an opportunity for customized handling of thread disposal. Manual invocation of the shutdown() method is also possible if the need arises to terminate the scope before its automatic closure.

    StructuredTaskScope introduces two classes, namely ShutDownOnSuccess and ShutDownOnFailure, designed to implement built-in shutdown policies. These policies monitor the success or failure of subtasks, promptly canceling the remaining running threads. In the existing setup, these classes can be seamlessly integrated to enhance control over concurrent workflows, as demonstrated in the provided example.

    Listing 3. Built-in shutdown policies

    
    void failFast() throws ExecutionException, InterruptedException {
       int[] planetIds = {1,2,3,-1,4};
       try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
         for (int planetId : planetIds) {
           scope.fork(() -> getPlanet(planetId));
         } 
         scope.join();
       }
     }
     void  succeedFast() throws ExecutionException, InterruptedException {
       int[] planetIds = {1,2};
       try (var scope = new StructuredTaskScope.ShutdownOnSuccess()) {
         for (int planetId : planetIds) {
           scope.fork(() -> getPlanet(planetId));
         } 
         scope.join();
       } catch (Exception e){
         System.out.println("Error: " + e);
      }
    } 
    public static void main(String[] args) {
      var myApp = new App();
      System.out.println("\n\r-- BEGIN succeedFast");
      try {
        myApp. succeedFast();
      } catch (Exception e) {
        System.out.println(e.getMessage());
      }      
      System.out.println("\n\r-- BEGIN failFast");
            try {
                myApp.failFast();
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
    
        }

    These policies will give output similar to below:

    
    -- BEGIN succeedFast
    BEGIN getPlanet()
    BEGIN getPlanet()
    Got a Planet: {"name":"Alderaan"}
    org.apache.http.impl.execchain.RetryExec execute
    INFO: I/O exception (java.net.SocketException) caught when processing request to {s}->https://swapi.dev:443: Closed by interrupt
    
    -- BEGIN failFast
    BEGIN getPlanet()
    BEGIN getPlanet()
    BEGIN getPlanet()
    BEGIN getPlanet()
    BEGIN getPlanet()
    Got a Planet: {"name":"Hoth"}
    Got a Planet: {"name":"Tatooine"}
    Error fetching planet information for ID: -1
    org.apache.http.impl.execchain.RetryExec execute
    INFO: I/O exception (java.net.SocketException) caught when processing request to {s}->https://swapi.dev:443: Closed by interrupt

    So what we have is a simple mechanism to initiate all the requests concurrently, and then cancel the rest when one either succeeds or fails via exception. From here, any customizations can be made. The structured concurrency documentation includes an example of collecting subtask results as they succeed or fail and then returning the results. This is fairly simply accomplished by overriding the join() method and watching the results of each task.

    StructuredTaskScope.Subtask

    One thing we have not seen in our example is watching the return values of subtasks. Each time StructuredTaskScope.fork() is called, a StructuredTaskScope.SubTask object is returned. We can make use of this to watch the state of the tasks. For example, in our sc() method, we could do the following:

    Listing 4. Using StructuredTaskScope.Subtask to watch state

    
    import java.util.concurrent.StructuredTaskScope.Subtask;
    import java.util.ArrayList;
    
    void sc() throws Exception {
          int[] planetIds = {1,2,3,4,5};
          ArrayList<Subtask> tasks = new ArrayList<Subtask>(planetIds.length); 
            try (var scope = new StructuredTaskScope<Object>()) {
              for (int planetId : planetIds) {
                tasks.add(scope.fork(() -> getPlanet(planetId)));
              } 
              scope.join();
            }catch (Exception e){
              System.out.println("Error: " + e);
            }
          for (Subtask t : tasks){
            System.out.println("Task: " + t.state());
          }
        }

    In this example, we take each task and hold it in an ArrayList, then output the state on them after join(). Note that the available states for Subtask are defined on it as enum. This new method will output something similar to this:

    
    -- BEGIN Structured Concurrency
    BEGIN getPlanet()
    BEGIN getPlanet()
    BEGIN getPlanet()
    BEGIN getPlanet()
    BEGIN getPlanet()
    Got a Planet: {"name":"Dagobah"}
    Got a Planet: {"name":"Hoth"}
    Got a Planet: {"name":"Tatooine"}
    Got a Planet: {"name":"Yavin IV"}
    Got a Planet: {"name":"Alderaan"}
    Task: SUCCESS
    Task: SUCCESS
    Task: SUCCESS
    Task: SUCCESS
    Task: SUCCESS

     

    In conclusion, the marriage of virtual threads and structured concurrency introduces a compelling paradigm shift for Java developers, offering a potent mechanism to parallelize diverse code segments with minimal overhead. While the allure of these new concurrency tools is undeniable, it’s crucial to approach their adoption with a nuanced understanding of the specific context and project requirements. Incorporating virtual threads and structured concurrency shouldn’t be a blind adherence; instead, it demands thoughtful consideration.

    The synergy of virtual threads and structured concurrency empowers developers with formidable capabilities. When confronted with scenarios where numerous tasks unfold concurrently, the virtual thread engine becomes a versatile ally, efficiently orchestrating tasks to alleviate bottlenecks. The inherent flexibility of the new thread model, coupled with structured concurrency, facilitates seamless customization and fine-tuning of concurrent behaviors to suit diverse needs.

    As the Java community embraces these groundbreaking concurrency capabilities, it will be intriguing to witness the innovative ways in which developers integrate them into applications, frameworks, and server architectures. The evolution of Java’s concurrency landscape promises to be dynamic, ushering in a new era of efficiency and flexibility in concurrent programming.

    Post Views: 159
    Share. Facebook Twitter Pinterest LinkedIn Tumblr Email
    ayaksız
    • Website

    Related Posts

    Experience Seamless Conversations with Google Meet’s Live AI Translations

    Mayıs 22, 2025

    Experience Virtual Fitting Rooms with Google’s New AI Feature

    Mayıs 22, 2025

    Microsoft Introduces AI-Driven Power Management and Updated Widgets in Windows 11

    Mayıs 22, 2025
    Add A Comment

    Comments are closed.

    Editors Picks
    8.5

    Apple Planning Big Mac Redesign and Half-Sized Old Mac

    Ocak 5, 2021

    Autonomous Driving Startup Attracts Chinese Investor

    Ocak 5, 2021

    Onboard Cameras Allow Disabled Quadcopters to Fly

    Ocak 5, 2021
    Top Reviews
    9.1

    Review: T-Mobile Winning 5G Race Around the World

    By sevketayaksiz
    8.9

    Samsung Galaxy S21 Ultra Review: the New King of Android Phones

    By sevketayaksiz
    8.9

    Xiaomi Mi 10: New Variant with Snapdragon 870 Review

    By sevketayaksiz
    Advertisement
    Demo
    Şevket Ayaksız
    Facebook X (Twitter) Instagram YouTube
    • Home
    • Adobe
    • microsoft
    • java
    • Oracle
    • Contact
    © 2025 Theme Designed by Şevket Ayaksız.

    Type above and press Enter to search. Press Esc to cancel.