首页 > 解决方案 > 在 Spring Boot 的 @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 更合适,请分享您的观点。

标签: javaspring-bootasynchronousfuturecompletable-future

解决方案


它们一开始就服务于完全不同的目的。在考虑处理一个或另一个需要多少之前,您可能首先想了解它们是如何工作的(所以很少的调用并不表示慢/快;这些数字在这种情况下毫无意义)。

这是您的相同示例:

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为它配置一个池就使用它不是一个好主意;否则它将消耗来自ForkJoinPool.


推荐阅读