我已经看过很多次此代码,但是不知道它的优点/缺点是什么。在Spring Boot应用程序中,我看到人们定义了这个bean。
@Bean
@Qualifier("heavyLoadBean")
public ExecutorService heavyLoadBean() {
return Executors.newWorkStealingPool();
}
然后,每当在服务层中创建CompletableFuture对象时,就会使用该heavyLoadBean。
public CompletionStage<T> myService() {
return CompletableFuture.supplyAsync(() -> doingVeryBigThing(), heavyLoadBean);
}
然后,控制器将调用该服务。
@GetMapping("/some/path")
public CompletionStage<SomeModel> doIt() {
return service.myService();
}
我不知道这样做的意义。 Spring Boot中的Tomcat具有x个线程。所有线程都用于处理用户请求。在这里使用不同的线程池有什么意义?无论如何,用户希望看到返回的响应。
答案 0 :(得分:1)
CompletableFuture
用于异步处理任务,假设在您的应用程序中,如果您有两个彼此独立的任务,则可以同时执行两个任务(以减少处理时间)
public CompletionStage<T> myService() {
CompletableFuture.supplyAsync(() -> doingVeryBigThing(), heavyLoadBean);
CompletableFuture.supplyAsync(() -> doingAnotherBigThing(), heavyLoadBean);
}
在上面的示例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);
}
如果不提供线程池,则默认情况下,提供的Supplier
将由ForkJoinPool.commonPool()
执行
公共静态CompletableFuture supplyAsync(供应商供应商)
返回一个新的CompletableFuture,它由在ForkJoinPool.commonPool()中运行的任务异步完成,并具有通过调用给定的Supplier所获得的值。
公共静态CompletableFuture supplyAsync(供应商, 执行者执行者)
返回一个新的CompletableFuture,它由在给定执行程序中运行的任务异步完成,并具有通过调用给定Supplier所获得的值。
答案 1 :(得分:-1)
请检查主要帖子和其他解决方案中的评论。他们将使您对Java 8 CompletableFuture有更多的了解。我只是感觉不到给出了正确的答案。
从我们的讨论中,我可以看到拥有一个不同的线程池而不是使用默认线程池的目的是主Web服务器(spring boot-tomcat)也使用了默认线程池。假设有8个线程。
如果我们用完所有8个线程,则服务器似乎无响应。但是,如果您使用其他线程池并在长时间运行的进程中耗尽该线程池,则代码中将出现其他错误。因此,服务器仍可以响应其他用户请求。
如果我错了,请纠正我。