Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it good to have dedicated ExecutorService for Spring Boot With Tomcat

I have seen this code many times but don't know what is the advantage/disadvantage for it. In Spring Boot applications, I saw people define this bean.

@Bean
@Qualifier("heavyLoadBean")
public ExecutorService heavyLoadBean() {
    return Executors.newWorkStealingPool();
}

Then whenever a CompletableFuture object is created in the service layer, that heavyLoadBean is used.

public CompletionStage<T> myService() {
   return CompletableFuture.supplyAsync(() -> doingVeryBigThing(), heavyLoadBean);
}

Then the controller will call the service.

@GetMapping("/some/path")
public CompletionStage<SomeModel> doIt() {
   return service.myService();
}

I don't see the point of doing that. Tomcat in Spring Boot has x number of threads. All the threads are used to process user requests. What is the point of using a different thread pool here? Anyway the user expects to see response coming back.

like image 735
TrongBang Avatar asked Nov 17 '22 13:11

TrongBang


1 Answers

CompletableFuture is used process the tasks asynchronously, suppose in your application if you have two tasks independent of each other then you can execute two tasks concurrently (to reduce the processing time)

public CompletionStage<T> myService() {
CompletableFuture.supplyAsync(() -> doingVeryBigThing(), heavyLoadBean);
CompletableFuture.supplyAsync(() -> doingAnotherBigThing(), heavyLoadBean);
}

In the above example doingVeryBigThing() and doingAnotherBigThing() two tasks which are independent of each other, so now these two tasks will be executed concurrently with two different threads from heavyLoadBean thread pool, try below example will print the two different thread names.

public CompletionStage<T> myService() {
CompletableFuture.supplyAsync(() -> System.out.println(Thread.currentThread().getName(), heavyLoadBean);
CompletableFuture.supplyAsync(() -> System.out.println(Thread.currentThread().getName(), heavyLoadBean);
}

If you don't provide the thread pool, by default supplied Supplier will be executed by ForkJoinPool.commonPool()

public static CompletableFuture supplyAsync(Supplier supplier)

Returns a new CompletableFuture that is asynchronously completed by a task running in the ForkJoinPool.commonPool() with the value obtained by calling the given Supplier.

public static CompletableFuture supplyAsync(Supplier supplier, Executor executor)

Returns a new CompletableFuture that is asynchronously completed by a task running in the given executor with the value obtained by calling the given Supplier.

like image 153
Deadpool Avatar answered Feb 23 '23 01:02

Deadpool