In this article, we’ll explore the Multi-threading support
provided in Spring or Spring Boot using Spring's @Async annotation.
Why to use @Async while using Spring Framework?
It supports Dependency injection and manages the life cycle of threads.
Internally it uses
ThreadPoolTaskExecutor is a JavaBean that provides an abstraction around
a java.util.concurrent.ThreadPoolExecutor instance and exposes it as a Spring
org.springframework.core.task.TaskExecutor. Further, it is highly configurable
through the properties of corePoolSize, maxPoolSize, queueCapacity,
allowCoreThreadTimeOut and keepAliveSeconds.
How to use @Async ?
We will annotate a bean method; @Async will make it execute in a separate
thread, i.e. the caller will not wait for the completion of the called method.
To enable this support we need to do couple of things as follows :
Exception Handling As you must have been noticed in above code snippet we already added RejectedExecutionHandler but that is not enough while handling Exceptions in multithreaded environment.
When a method return type is a Future, exception handling is easy. Future.get() method will throw the exception. But if the return type is void, exceptions will not be propagated to the calling thread. So, we need to add extra configurations to handle exceptions.
We'll create a custom
async exception handler by implementing
AsyncUncaughtExceptionHandler interface. The
handleUncaughtException() method is invoked when there are any uncaught asynchronous exceptions:
Note : CompletableFuture, which was introduced in Java 8, provides an easy way to write asynchronous, non-blocking, and multi-threaded code.
The Future interface was introduced in Java 5 to handle asynchronous computations. But, this interface did not have any methods to combine multiple asynchronous computations and handle all the possible errors. The CompletableFuture implements Future interface, it can combine multiple asynchronous computations, handle possible errors and offers much more capabilities.
Conclusionwe have seen ThreadPoolTaskExecutor is a powerful abstraction around a java.util.concurrent.ThreadPoolExecutor and how we can implemented multithreading application using @Async.