How to achieve async/await functionality in Java?

How can I achieve async/await functionality in Java?

As a C# developer who occasionally works with Java, I’m wondering if there is a Java async await equivalent. In simple terms, how can I replicate the following C# code in Java?

async Task<int> AccessTheWebAsync()
{ 
    HttpClient client = new HttpClient();
    var urlContents = await client.GetStringAsync("http://msdn.microsoft.com");
    return urlContents.Length;
}

Ah, when it comes to achieving async/await functionality in Java, it’s not as straightforward as it is in C#, but don’t worry! From my experience, we can still replicate this behavior using CompletableFuture in Java. Here’s an example to get you started with java async await functionality:

import java.net.http.*;
import java.net.URI;
import java.util.concurrent.*;

public class AsyncExample {
    public static CompletableFuture<Integer> accessTheWebAsync() {
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("http://msdn.microsoft.com"))
                .build();

        return client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
                .thenApply(HttpResponse::body)
                .thenApply(String::length);
    }

    public static void main(String[] args) {
        accessTheWebAsync().thenAccept(length -> 
            System.out.println("Downloaded content length: " + length)
        ).join();
    }
}

:white_check_mark: Pros:

  • Non-blocking approach.
  • Works great with modern Java HTTP clients.
  • Chainable with .thenApply(), .thenAccept(), etc.

This method closely mimics the behavior of async/await, making it much easier to work with asynchronous code in Java. If you are working with Java 8 or later, this is your go-to method for java async await functionality.

Good point, @babitakumari I totally agree with that approach, but here’s a little extra for those who might still be working with older Java versions (pre-Java 8) or prefer a bit more manual control. You can leverage ExecutorService for async tasks, giving you a bit more flexibility in managing threads and the flow of tasks. It’s still an effective way to simulate java async await behavior in earlier versions.

Check out this example:

import java.net.*;
import java.io.*;
import java.util.concurrent.*;

public class AsyncExample {
    public static Future<Integer> accessTheWebAsync(ExecutorService executor) {
        return executor.submit(() -> {
            URL url = new URL("http://msdn.microsoft.com");
            BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
            StringBuilder content = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                content.append(line);
            }
            return content.length();
        });
    }

    public static void main(String[] args) throws Exception {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<Integer> future = accessTheWebAsync(executor);
        System.out.println("Downloaded content length: " + future.get()); // Blocks until result is ready
        executor.shutdown();
    }
}

:white_check_mark: Pros:

  • Works with older Java versions.
  • Provides granular control over thread management.

:x: Cons:

  • The call to future.get() is blocking, which could impact performance.
  • Requires managing thread pools manually.

It’s still a solid method for achieving java async await if you want full control over how your threads are managed."

Great additions, guys! But here’s where things get super interesting – Java is evolving! With the introduction of Project Loom in Java 21+, we’re now looking at a much cleaner way to handle async tasks. It’s like Java’s version of async/await, but even simpler! Virtual threads allow us to write async code almost as if it’s synchronous – no more complex thread management or chained CompletableFuture calls.

Here’s how easy it can be with virtual threads in Java:

public static void main(String[] args) throws Exception {
    try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
        Future<Integer> future = executor.submit(() -> {
            var client = HttpClient.newHttpClient();
            var request = HttpRequest.newBuilder()
                .uri(URI.create("http://msdn.microsoft.com"))
                .build();
            var response = client.send(request, HttpResponse.BodyHandlers.ofString());
            return response.body().length();
        });

        System.out.println("Downloaded content length: " + future.get()); // No thread pool blocking!
    }
}

:white_check_mark: Pros:

  • Virtual threads are lightweight, and thousands can run concurrently without issues.
  • More readable and simpler than CompletableFuture chains.
  • No need for manual thread pool management – Java takes care of it for you.

This is truly the future of java async await and will make handling asynchronous code in Java as easy as pie!"