Java 21 async/await

Eugene 60 Published: 09/13/2024

Java 21 async/await

Here's an explanation of Java 21's async/await feature:

Java 21 was released in September 2021, and it introduced several significant language features. One of the most exciting new features is support for asynchronous programming using async and await.

Async/await allows developers to write asynchronous code that looks and feels synchronous. It enables you to write code that can handle multiple tasks concurrently, without having to deal with the complexity of low-level threading and synchronization constructs.

Here's a basic example of how you might use async/await in Java 21:

import java.time.Duration;

import java.time.Instant;

public class AsyncAwaitExample {

public static void main(String[] args) throws InterruptedException, ExecutionException {

Instant start = Instant.now();

// Start a task that will take some time to complete

CompletableFuture task = CompletableFuture.runAfterDelay(() -> {

try {

Thread.sleep(Duration.ofSeconds(2).toMillis());

return "Task completed";

} catch (InterruptedException e) {

throw new RuntimeException(e);

}

}, Duration.ofSeconds(1));

// Use async/await to wait for the task to complete

CompletableFuture result = task.thenApply(String::toUpperCase);

String finalResult = await(result, 5, TimeUnit.SECONDS); // Wait up to 5 seconds

System.out.println("Task completed: " + finalResult);

System.out.println("Total time taken: " + Duration.between(start, Instant.now()).toMillis() + " milliseconds");

}

public static V await(CompletableFuture future, long timeout, TimeUnit unit) throws ExecutionException, TimeoutException {

return future.get(timeout, unit.toMillis());

}

}

In this example, we use runAfterDelay to start a task that will take some time to complete. We then use thenApply to transform the result of the task and pass it to an async/await method.

The async/await method waits for up to 5 seconds for the task to complete, and then returns the result if it's available within the timeout. If the task doesn't complete within the timeout, a TimeoutException is thrown.

This example demonstrates how you can use async/await to write asynchronous code that looks synchronous. You can also use this pattern with other types of tasks, such as network requests or database queries, to handle multiple tasks concurrently without blocking your main thread.

Java 21's async/await feature makes it easier to write and reason about asynchronous code, which is essential for building modern applications that need to handle multiple tasks concurrently.

Why does Java not have async await?

Java is a statically-typed, object-oriented programming language that is known for its simplicity and flexibility. Despite being widely used, Java has some limitations when it comes to asynchronous programming. One of the most notable absences is the lack of built-in support for async/await syntax.

In modern applications, handling asynchronous tasks is crucial for improving performance, scalability, and responsiveness. Libraries like RxJava and CompletableFuture have filled this gap in part, but they are not as straightforward or intuitive as the async/await syntax found in languages like C# or F#.

The main reason Java does not have built-in support for async/await is its historical roots and design choices. When Java was first developed, asynchronous programming wasn't as crucial as it is today. The language focused more on concurrency using threads, rather than handling asynchronous tasks.

Another reason might be that the Java Community Process (JCP) has historically favored a more explicit approach to dealing with concurrency. This is reflected in Java's use of threads, locks, and synchronized blocks for achieving concurrency. Asynchronous programming often relies on implicit context switching between tasks, which can lead to unexpected behavior if not handled correctly.

Additionally, Java has a strong focus on thread safety, which sometimes leads to more verbose code when handling asynchronous tasks. The language's built-in support for threads, locks, and concurrent collections provides a robust foundation for building scalable applications, but it may not be as straightforward or intuitive as async/await syntax.

However, this does not mean that Java developers cannot handle asynchronous programming. As mentioned earlier, libraries like RxJava and CompletableFuture can help simplify the process. The Java standard library also provides classes like ExecutorService and ScheduledExecutorService, which enable scheduling tasks asynchronously.

In recent years, there has been increased interest in adding async/await syntax to Java. Some proposals have been made for a future version of Java, but so far, none have been implemented. It's possible that future developments will lead to improved support for asynchronous programming in Java.

In conclusion, while Java lacks built-in support for async/await syntax, it still provides robust tools and libraries for handling concurrency and asynchronous tasks. As the language continues to evolve, we may see improvements or even the addition of async/await syntax in the future. For now, developers can rely on libraries like RxJava and CompletableFuture to simplify their asynchronous programming needs.

Sources:

Oracle Java API (https://docs.oracle.com/javase/)

RxJava documentation (https://github.com/ReactiveX/RxJava) CompletableFuture documentation (https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html) "Why does Java not have async/await?" by JavaTutorials (https://javatutorials.net/async-await-java/)