Asynchronous Programming in Java - Baeldung
Asynchronous Programming in Java - Baeldung
Get started with Spring 5 and Spring Boot 2, through the Learn Spring course:
>> CHECK OUT THE COURSE (/ls-course-start)
1. Overview
With the growing demand for writing non-blocking code, we need ways to execute the code asynchronously.
In this tutorial, we'll look at a few ways to achieve asynchronous programming (/cs/async-vs-multi-threading) in Java. We'll also explore a few Java libraries that
provide out-of-the-box solutions.
Further reading:
Guide To CompletableFuture (/java-completablefuture)
Quick and practical guide to Java 8's CompletableFuture.
Read more (/java-completablefuture) →
2.1. Thread
We can create a new thread to perform any operation asynchronously. With the release of lambda expressions (/java-8-lambda-expressions-tips) in Java 8, it's cleaner
and more readable.
Let's create a new thread that computes and prints the factorial of a number:
2.2. FutureTask
Since Java 5, the Future interface provides a way to perform asynchronous operations using the FutureTask (/java-future#1-implementing-futures-with-futuretask).
We can use the submit method of the ExecutorService (https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/ExecutorService.html)
to perform the task asynchronously and return the instance of the FutureTask.
So let's find the factorial of a number:
ExecutorService threadpool = Executors.newCachedThreadPool();
Future<Long> futureTask = threadpool.submit(() -> factorial(number));
while (!futureTask.isDone()) {
System.out.println("FutureTask is not finished yet...");
}
long result = futureTask.get();
threadpool.shutdown();
Here we've used the isDone method provided by the Future interface to check if the task is completed. Once finished, we can retrieve the result using the get method.
2.3. CompletableFuture
Java 8 introduced CompletableFuture (/java-completablefuture) with a combination of a Future and CompletionStage
(https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/CompletionStage.html). It provides various methods like supplyAsync,
runAsync, and thenApplyAsync for asynchronous programming.
Now let's use the CompletableFuture in place of the FutureTask to find the factorial of a number:
AD
(https://ads.freestar.com/?
CompletableFuture<Long> completableFuture = CompletableFuture.supplyAsync(() -> utm_campaign=branding&utm_medium=banner&utm_source=baeldung.com&utm_conten
factorial(number));
while (!completableFuture.isDone()) { mid_2)
System.out.println("CompletableFuture is not finished yet...");
}
long result = completableFuture.get();
We don't need to use the ExecutorService explicitly. The CompletableFuture internally uses ForkJoinPool (/java-fork-join) to handle the task asynchronously.
Thus, it makes our code a lot cleaner.
3. Guava
Guava (/guava-21-new) provides the ListenableFuture (https://guava.dev/releases/28.2-jre/api/docs/index.html?
com/google/common/util/concurrent/ListenableFuture.html) class to perform asynchronous operations.
First, we'll add the latest guava (https://mvnrepository.com/artifact/com.google.guava/guava) Maven dependency:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
</dependency>
Futures.addCallback(
factorialFuture,
new FutureCallback<Long>() {
public void onSuccess(Long factorial) {
System.out.println(factorial);
}
public void onFailure(Throwable thrown) {
thrown.getCause();
}
},
service);
4. EA Async
Electronic Arts brought the async-await feature from .NET to the Java ecosystem through the ea-async library (https://github.com/electronicarts/ea-async).
This library allows writing asynchronous (non-blocking) code sequentially. Therefore, it makes asynchronous programming easier and scales naturally.
First, we'll add the latest ea-async (https://mvnrepository.com/artifact/com.ea.async/ea-async) Maven dependency to the pom.xml:
<dependency>
<groupId>com.ea.async</groupId>
<artifactId>ea-async</artifactId>
<version>1.2.3</version>
</dependency>
Then we'll transform the previously discussed CompletableFuture code by using the await method provided by EA's Async (https://javadoc.io/doc/com.ea.async/ea-
async/latest/com/ea/async/Async.html) class:
static {
Async.init();
}
Here we make a call to the Async.init method in the static block to initialize the Async runtime instrumentation.
Async instrumentation transforms the code at runtime, and rewrites the call to the await method to behave similarly to using the chain of CompletableFuture.
Therefore, the call to the await method is similar to calling Future.join.
We can use the – javaagent JVM parameter for compile-time instrumentation. This is an alternative to the Async.init method:
try {
String hello = await(hello());
String helloWorld = await(mergeWorld(hello));
await(CompletableFuture.runAsync(() -> print(helloWorld)));
} catch (Exception e) {
e.printStackTrace();
}
The implementation resembles the sequential blocking code; however, the await method doesn't block the code.
As discussed, all calls to the await method will be rewritten by the Async instrumentation to work similarly to the Future.join method.
So once the asynchronous execution of the hello method is finished, the Future result is passed to the mergeWorld method. Then the result is passed to the last
execution using the CompletableFuture.runAsync method.
5. Cactoos
Cactoos is a Java library based on object-oriented principles.
It's an alternative to Google Guava and Apache Commons that provides common objects for performing various operations.
First, let's add the latest cactoos (https://mvnrepository.com/artifact/org.cactoos/cactoos) Maven dependency:
<dependency>
<groupId>org.cactoos</groupId>
<artifactId>cactoos</artifactId>
<version>0.43</version>
</dependency>
Here the apply method executes the operation using the ExecutorService.submit method, and returns an instance of the Future interface.
AD
Similarly, the Async class has the exec method that provides the same feature without a return value. (https://ads.freestar.com/?
utm_campaign=branding&utm_medium=banner&utm_source=baeldung.com&utm_content
Note: the Cactoos library is in the initial stages of development and may not be appropriate for production use yet.
6. Jcabi-Aspects
Jcabi-Aspects provides the @Async (https://aspects.jcabi.com/apidocs-0.22.6/com/jcabi/aspects/Async.html) annotation for asynchronous programming through
AspectJ (/aspectj) AOP aspects.
First, let's add the latest jcabi-aspects (https://mvnrepository.com/artifact/com.jcabi/jcabi-aspects) Maven dependency:
<dependency>
<groupId>com.jcabi</groupId>
<artifactId>jcabi-aspects</artifactId>
<version>0.22.6</version>
</dependency>
The jcabi-aspects library requires AspectJ runtime support, so we'll add the aspectjrt (https://mvnrepository.com/artifact/org.aspectj/aspectjrt) Maven dependency:
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.5</version>
</dependency>
Next, we'll add the jcabi-maven-plugin (https://mvnrepository.com/artifact/com.jcabi/jcabi-maven-plugin) plugin that weaves the binaries with AspectJ aspects. The
plugin provides the ajc goal that does all the work for us:
<plugin>
<groupId>com.jcabi</groupId>
<artifactId>jcabi-maven-plugin</artifactId>
<version>0.14.1</version>
<executions>
<execution>
<goals>
<goal>ajc</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>1.9.1</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.1</version>
</dependency>
</dependencies>
</plugin>
Now we're all set to use the AOP aspects for asynchronous programming:
@Async
@Loggable
public Future<Long> factorialUsingJcabiAspect(int number) {
Future<Long> factorialFuture = CompletableFuture.supplyAsync(() -> factorial(number));
return factorialFuture;
}
When we compile the code, the library will inject AOP advice in place of the @Async annotation through AspectJ weaving, for the asynchronous execution of the
factorialUsingJcabiAspect method.
Let's compile the class using the Maven command:
mvn install
We can verify if our class is woven correctly by checking the logs in the jcabi-ajc.log file generated by the Maven plugin:
Then we'll run the class as a simple Java application, and the output will look like:
As we can see, a new daemon thread, jcabi-async, is created by the library that performed the task asynchronously.
Similarly, the logging is enabled by the @Loggable (https://aspects.jcabi.com/apidocs-0.22.6/com/jcabi/aspects/Loggable.html) annotation provided by the library.
7. Conclusion
In this article, we learned a few ways of asynchronous programming in Java.
To begin with, we explored Java's in-built features like FutureTask and CompletableFuture for asynchronous programming. Then we examined a few libraries, like EA
Async and Cactoos, with out-of-the-box solutions.
AD
We also discussed the support of performing tasks asynchronously using Guava's ListenableFuture and Futures classes. Finally, (https://ads.freestar.com/?
we touched on the jcabi-AspectJ
utm_campaign=branding&utm_medium=banner&utm_source=baeldung.com&utm_content
library that provides AOP features through its @Async annotation for asynchronous method calls.
As usual, all the code implementations are available over on GitHub (https://github.com/eugenp/tutorials/tree/master/core-java-modules/core-java-concurrency-
advanced-3).
Get started with Spring 5 and Spring Boot 2, through the Learn Spring course:
>> CHECK OUT THE COURSE (/ls-course-end)
guide)
2 COMMENTS Oldest
View Comments
COURSES
ALL COURSES (/ALL-COURSES)
ALL BULK COURSES (/ALL-BULK-COURSES)
ALL BULK TEAM COURSES (/ALL-BULK-TEAM-COURSES)
THE COURSES PLATFORM (HTTPS://COURSES.BAELDUNG.COM)
SERIES
JAVA “BACK TO BASICS” TUTORIAL (/JAVA-TUTORIAL)
JACKSON JSON TUTORIAL (/JACKSON)
APACHE HTTPCLIENT TUTORIAL (/HTTPCLIENT-GUIDE)
REST WITH SPRING TUTORIAL (/REST-WITH-SPRING-SERIES)
SPRING PERSISTENCE TUTORIAL (/PERSISTENCE-WITH-SPRING-SERIES)
SECURITY WITH SPRING (/SECURITY-SPRING)
SPRING REACTIVE TUTORIALS (/SPRING-REACTIVE-GUIDE)
ABOUT
ABOUT BAELDUNG (/ABOUT)
THE FULL ARCHIVE (/FULL_ARCHIVE)
EDITORS (/EDITORS)
JOBS (/TAG/ACTIVE-JOB/)
OUR PARTNERS (/PARTNERS)
PARTNER WITH BAELDUNG (/ADVERTISE)