Thursday, July 8, 2021

Spring Boot - Multi threading using @Async

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 :

  • Add the @EnableAsync Annotation to a configuration class
  • customize the ThreadPoolTaskExecutor .


  • Add @Async Annotation to a Method

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.


Conclusion

we have seen ThreadPoolTaskExecutor is a powerful abstraction around a java.util.concurrent.ThreadPoolExecutor and how we can implemented multithreading application using @Async.