I've implemented asynchronous execution for a method in my application using Spring Boot @Async. I'm having a custom thread pool with 20 thread. In a for loop calling the async method for 30 times.
Each individual request is executing asynchronously but when i made two different requests at the same time to my API from browser, first request is executing and then second. Not both requests executing the same method parallely.
I thought when first request reach the app, it's started executing the async method and since it's being executing for 30 times and my pool is having 20 threads, all threads are busy in executing first request. So even second request came for execution also since the pool of threads busy, the other request is waiting till a thread becomes free in the pool.
Can we have separate thread pool for each individual request. or any way that we can make execution of each request separate independent of other request processing.
Here is my code sample.
@SpringBootApplication
@EnableAsync
public class AppBootStrap
{
public static void main(String[] args)
{
SpringApplication.run(AppBootStrap.class, args);
}
@Bean
public AsyncTaskService asyncTaskService() {
return new AsyncTaskService();
}
@Bean(name="customExecutor")
public Executor taskExecutor() {
ThreadPoolTaskExecutor poolExecutor = new ThreadPoolTaskExecutor();
poolExecutor.setCorePoolSize(10);
poolExecutor.setMaxPoolSize(20);
poolExecutor.setThreadNamePrefix("customPoolExecutor");
poolExecutor.initialize();
return poolExecutor;
}
}
**Controller Class:**
@RestController
public class TaskController
{
@Autowired
private TaskService taskService;
@RequestMapping("/performAction")
public void performAction() {
taskService.performAction();
}
}
**Service class**
@Service
public class TaskService
{
@Autowired
private AsyncTaskService asyncTaskService;
public void performAction()
{
for(int i = 0; i < 30; i++) {
asyncTaskService.greetings(i);
}
}
}
**Async Method Class**
public class AsyncTaskService
{
@Async
public void greetings(Integer i)
{
try
{
Thread.sleep(500 * (i + 10));
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println("Welcome to Async Service: " + i);
}
}
@Bean(name = "apiTaskExecutor")
public ThreadPoolTaskExecutor apiTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(20);
executor.setMaxPoolSize(100);
executor.setQueueCapacity(50);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
@Bean(name = "lruTaskExecutor")
public ThreadPoolTaskExecutor lruTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(100);
executor.setMaxPoolSize(200);
executor.setQueueCapacity(500);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
The Way to do this is to create two Thread different Thread Pools using Different Qualifier names. (As shown above)
@Autowired
@Qualifier("apiTaskExecutor")
private ThreadPoolTaskExecutor apiTaskExecutor;
Then autowire the required pool using the qualifier you have given . You can also use the @Async annotation instead of autowiring . I prefer this way.
If I am not wrong this way of having different thread pools for different Tasks is known as bulkhead pattern.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With