在春季启动时在@Async批注中使用CompletableFuture.supplyAsync和CompletableFuture.completedFuture

问题描述

我有以下方法:

@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的线程。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...