【问题标题】:use of CompletableFuture.supplyAsync and CompletableFuture.completedFuture within @Async annotation in spring boot在 Spring Boot 的 @Async 注解中使用 CompletableFuture.supplyAsync 和 CompletableFuture.completedFuture
【发布时间】:2021-02-19 10:39:30
【问题描述】:

我有以下方法:

@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 更合适,请分享您的观点。

【问题讨论】:

    标签: java spring-boot asynchronous future completable-future


    【解决方案1】:

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

    这是你的同一个例子:

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

    【讨论】:

    • 感谢您的澄清,但是如果 completedFuture() 是由主线程(而不是 ForkJoinPool 中的另一个线程)执行的,那么基本上使用它有什么需要,因为我们通常可以调用我们的方法,甚至不用使用 completedFuture ?
    • @MortezaN 在 this 的情况下它由主线程完成。没有什么可以阻止您或其他任何人分享此CompletableFuture,以便其他线程可以完成它。
    • 在异步spring的情况下,我们已经配置了executor。那么这是否意味着我们应该更喜欢supplyAsync 来包装阻塞操作?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-20
    • 2021-12-20
    • 1970-01-01
    • 1970-01-01
    • 2019-03-29
    • 1970-01-01
    相关资源
    最近更新 更多