{"id":1987,"date":"2025-09-23T15:36:47","date_gmt":"2025-09-23T03:36:47","guid":{"rendered":"https:\/\/www.ronella.xyz\/?p=1987"},"modified":"2026-01-12T08:54:29","modified_gmt":"2026-01-11T19:54:29","slug":"mastering-asynchronous-programming-in-java-with-completablefuture-and-virtual-threads","status":"publish","type":"post","link":"https:\/\/www.ronella.xyz\/?p=1987","title":{"rendered":"Asynchronous Programming in Java with CompletableFuture and Virtual Threads"},"content":{"rendered":"<p>Java's <strong>CompletableFuture<\/strong> provides a powerful and flexible framework for asynchronous programming. Introduced in Java 8, it allows writing non-blocking, event-driven applications with simple and readable code. With Java 21 and Project Loom, virtual threads can be combined with CompletableFutures to achieve highly scalable concurrency with minimal overhead. This article explores the core usage patterns of CompletableFuture and how to leverage virtual threads effectively.<\/p>\n<h2>Basics of CompletableFuture Usage<\/h2>\n<p>At its simplest, a CompletableFuture represents a future result of an asynchronous computation. You can create one that runs asynchronously using the <code>supplyAsync()<\/code> or <code>runAsync()<\/code> methods.<\/p>\n<ul>\n<li><strong>supplyAsync()<\/strong> runs a background task that returns a result.<\/li>\n<li><strong>runAsync()<\/strong> runs a background task with no returned result.<\/li>\n<\/ul>\n<p>Example:<\/p>\n<pre><code class=\"language-java\">CompletableFuture&lt;String&gt; future = CompletableFuture.supplyAsync(() -&gt; &quot;Hello World&quot;);\nSystem.out.println(future.get());  \/\/ Blocks until the result is ready<\/code><\/pre>\n<p>In this example, the supplier runs asynchronously, and the main thread waits for its result using <code>get()<\/code>. The computation executes in the common <strong>ForkJoinPool<\/strong> by default.<\/p>\n<h2>Chaining and Composing Tasks<\/h2>\n<p>CompletableFuture excels at composing asynchronous tasks without nested callbacks:<\/p>\n<ul>\n<li><strong>thenApply()<\/strong> transforms the result of a completed future.<\/li>\n<li><strong>thenAccept()<\/strong> consumes the result without returning anything.<\/li>\n<li><strong>thenRun()<\/strong> runs a task once the future is complete.<\/li>\n<li><strong>thenCombine()<\/strong> combines results of two independent futures.<\/li>\n<li><strong>thenCompose()<\/strong> chains dependent futures for sequential asynchronous steps.<\/li>\n<\/ul>\n<p>Example of chaining:<\/p>\n<pre><code class=\"language-java\">CompletableFuture.supplyAsync(() -&gt; 10)\n    .thenApply(result -&gt; result + 20)\n    .thenAccept(result -&gt; System.out.println(&quot;Result: &quot; + result));<\/code><\/pre>\n<p>Example of combining:<\/p>\n<pre><code class=\"language-java\">CompletableFuture&lt;Integer&gt; f1 = CompletableFuture.supplyAsync(() -&gt; 10);\nCompletableFuture&lt;Integer&gt; f2 = CompletableFuture.supplyAsync(() -&gt; 20);\nCompletableFuture&lt;Integer&gt; combined = f1.thenCombine(f2, Integer::sum);\nSystem.out.println(combined.get());  \/\/ 30<\/code><\/pre>\n<p>These patterns allow building complex, non-blocking workflows with clean and expressive code.<\/p>\n<h2>Exception Handling<\/h2>\n<p>CompletableFuture allows robust error handling without complicating the flow:<\/p>\n<ul>\n<li>Use <strong>exceptionally()<\/strong> to recover with a default value on error.<\/li>\n<li>Use <strong>handle()<\/strong> to process outcome result or exception.<\/li>\n<li>Use <strong>whenComplete()<\/strong> to perform an action regardless of success or failure.<\/li>\n<\/ul>\n<p>Example:<\/p>\n<pre><code class=\"language-java\">CompletableFuture.supplyAsync(() -&gt; {\n    if (true) throw new RuntimeException(&quot;Failure&quot;);\n    return &quot;Success&quot;;\n}).exceptionally(ex -&gt; &quot;Recovered from &quot; + ex.getMessage())\n  .thenAccept(System.out::println);  \/\/ Outputs: Recovered from java.lang.RuntimeException: Failure<\/code><\/pre>\n<h2>Waiting for Multiple Futures<\/h2>\n<p>The <code>allOf()<\/code> method is used to wait for multiple CompletableFutures to finish:<\/p>\n<pre><code class=\"language-java\">List&lt;CompletableFuture&lt;String&gt;&gt; futures = List.of(\n    CompletableFuture.completedFuture(&quot;A&quot;),\n    CompletableFuture.completedFuture(&quot;B&quot;),\n    CompletableFuture.completedFuture(&quot;C&quot;));\n\nCompletableFuture&lt;Void&gt; allDone = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));\nallDone.join();  \/\/ Wait until all futures complete<\/code><\/pre>\n<p>This enables executing parallel asynchronous operations efficiently.<\/p>\n<h2>Using CompletableFuture with Virtual Threads<\/h2>\n<p>Java 21 introduces <strong>virtual threads<\/strong>, lightweight threads that allow massive concurrency with minimal resource consumption. To use CompletableFutures on virtual threads, create an executor backed by virtual threads and pass it to async methods.<\/p>\n<p>Example:<\/p>\n<pre><code class=\"language-java\">try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {\n    CompletableFuture&lt;Void&gt; future = CompletableFuture.runAsync(() -&gt; {\n        System.out.println(&quot;Running in virtual thread: &quot; + Thread.currentThread());\n        try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }\n        System.out.println(&quot;Task completed&quot;);\n    }, executor);\n\n    future.join();\n}<\/code><\/pre>\n<ul>\n<li>The executor is created with <code>Executors.newVirtualThreadPerTaskExecutor()<\/code>.<\/li>\n<li>Async tasks run on virtual threads, offering high scalability.<\/li>\n<li>The executor must be closed to release resources and stop accepting tasks; using try-with-resources is recommended.<\/li>\n<\/ul>\n<p>All operations such as <code>thenApplyAsync()<\/code> or <code>thenCombineAsync()<\/code> can similarly take the virtual thread executor to keep subsequent stages on virtual threads.<\/p>\n<h2>Summary<\/h2>\n<ul>\n<li><strong>CompletableFuture<\/strong> allows flexible, readable asynchronous programming.<\/li>\n<li>Tasks can be created, chained, combined, and composed easily.<\/li>\n<li>Robust exception handling is built-in.<\/li>\n<li><code>allOf()<\/code> allows waiting on multiple futures.<\/li>\n<li>With <strong>virtual threads<\/strong>, CompletableFuture scales brilliantly by offloading async tasks to lightweight threads.<\/li>\n<li>Always close virtual thread executors to properly release resources.<\/li>\n<\/ul>\n<p>Using CompletableFuture with virtual threads simplifies asynchronous programming and enables writing performant scalable Java applications with clean and maintainable code.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Java&#8217;s CompletableFuture provides a powerful and flexible framework for asynchronous programming. Introduced in Java 8, it allows writing non-blocking, event-driven applications with simple and readable code. With Java 21 and Project Loom, virtual threads can be combined with CompletableFutures to achieve highly scalable concurrency with minimal overhead. This article explores the core usage patterns of [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[85],"tags":[],"_links":{"self":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts\/1987"}],"collection":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1987"}],"version-history":[{"count":2,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts\/1987\/revisions"}],"predecessor-version":[{"id":2045,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts\/1987\/revisions\/2045"}],"wp:attachment":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1987"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1987"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1987"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}