问题描述
我有以下方法:
@EnableAsync
@Service
Class MyService{
private String processRequest() {
log.info("Start processing request");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
log.info("Completed processing request");
return RESULT;
}
@Async
public CompletableFuture<String> getSupplyAsyncResult(){
CompletableFuture<String> future
= CompletableFuture.supplyAsync(this::processRequest);
return future;
}
@Async
public CompletableFuture<String> getCompletedFutureResult(){
CompletableFuture<String> future
= CompletableFuture.supplyAsync(this::processRequest);
return future;
}
以及控制器中的以下端点:
@RequestMapping(path = "/asyncSupplyAsync",method = RequestMethod.GET)
public CompletableFuture<String> getValueAsyncUsingCompletableFuture() {
log.info("Request received");
CompletableFuture<String> completableFuture
= myService.getSupplyAsyncResult();
log.info("Servlet thread released");
return completableFuture;
}
和
@RequestMapping(path = "/asyncCompletable",method = RequestMethod.GET)
public CompletableFuture<String> getValueAsyncUsingCompletableFuture() {
log.info("Request received");
CompletableFuture<String> completableFuture
= myService.getCompletedFutureResult();
log.info("Servlet thread released");
return completableFuture;
}
为什么有人会在Spring端点的@Async方法中使用 completableFuture.supplyAsync ? 我认为使用 completableFuture.completedFuture 更合适,请分享您的观点。
解决方法
它们起初的目的完全不同。在考虑一个或另一个要花多少钱之前,您可能想要首先了解它们的工作原理(因此,很少的呼叫无论如何都不表示慢/快;在这种情况下,这些数字毫无意义)。
这是您遇到的相同示例:
print(usb.Description)
您可以运行此命令,然后更改实现(通过取消注释public class SO64718973 {
public static void main(String[] args) {
System.out.println("dispatching to CF...");
//CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> processRequest());
CompletableFuture<String> future = CompletableFuture.completedFuture(processRequest());
System.out.println("done dispatching to CF...");
future.join();
}
private static String processRequest() {
System.out.println("Start processing request");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("Completed processing request");
return "RESULT";
}
}
)并查看发生CompletableFuture.supplyAsync
的位置。您会注意到System.out.println
将阻塞completedFuture
线程,直到执行为止,而main
将在另一个线程中运行。因此,这并不是一个错误的错误,而是一个错误的错误,这取决于您的用例。
通常,最好不使用supplyAsync
为其配置一个池;否则它将消耗来自CompletableFuture.supplyAsync
的线程。