使用 Tomcat 为 Spring Boot 提供专用的 ExecutorService 好吗

Tro*_*ang 5 java-8 spring-boot

我已经多次看到这段代码,但不知道它的优点/缺点是什么。在 Spring Boot 应用程序中,我看到人们定义了这个 bean。

@Bean
@Qualifier("heavyLoadBean")
public ExecutorService heavyLoadBean() {
    return Executors.newWorkStealingPool();
}
Run Code Online (Sandbox Code Playgroud)

然后每当在服务层中创建 CompletableFuture 对象时,就会使用该重载Bean。

public CompletionStage<T> myService() {
   return CompletableFuture.supplyAsync(() -> doingVeryBigThing(), heavyLoadBean);
}
Run Code Online (Sandbox Code Playgroud)

然后控制器将调用该服务。

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

我看不出这样做的意义。Spring Boot 中的 Tomcat 有 x 个线程。所有线程都用于处理用户请求。在这里使用不同的线程池有什么意义?无论如何,用户希望看到响应回来。

Dea*_*ool 1

CompletableFuture用于异步处理任务,假设在您的应用程序中,如果您有两个彼此独立的任务,那么您可以同时执行两个任务(以减少处理时间)

public CompletionStage<T> myService() {
CompletableFuture.supplyAsync(() -> doingVeryBigThing(), heavyLoadBean);
CompletableFuture.supplyAsync(() -> doingAnotherBigThing(), heavyLoadBean);
}
Run Code Online (Sandbox Code Playgroud)

在上面的示例中doingVeryBigThing()doingAnotherBigThing()两个任务彼此独立,因此现在这两个任务将使用heavyLoadBean线程池中的两个不同线程并发执行,尝试下面的示例将打印两个不同的线程名称。

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

如果你不提供线程池,默认情况下提供的Supplier将由ForkJoinPool.commonPool()

public static CompletableFuture SupplyAsync(供应商供应商)

返回一个新的 CompletableFuture,它由 ForkJoinPool.commonPool() 中运行的任务异步完成,其值是通过调用给定的供应商获得的。

public static CompletableFuture SupplyAsync(Supplier 供应商,Executor 执行者)

返回一个新的 CompletableFuture,该任务由给定执行器中运行的任务异步完成,并通过调用给定的供应商获得值。