【问题标题】:How to run combined CompletableFutures asynchronously如何异步运行组合的 CompletableFutures
【发布时间】:2022-01-07 15:25:42
【问题描述】:

我想通过调用返回不同对象类型列表的不同服务来加载应用程序启动时的数据。每个服务调用 DAO 类来读取一些数据。所以我创建了个人CompletableFuture,比如:

CompletableFuture<List<DTO1> future1 = CompletableFuture.supplyAsync(() -> service1.callMethod1());
CompletableFuture<List<DTO2> future2 = CompletableFuture.supplyAsync(() -> service2.callMethod2());
CompletableFuture<List<DTO3> future3 = CompletableFuture.supplyAsync(() -> service3.callMethod3());

并像这样组合它们:

CompletableFuture<Void> combinedFuture = CompletableFuture.allOf(future1, future2, future3);

如果我这样做:

combinedFuture.thenRunAsync(()->future1.join(), future2.join(), future3.join())

然后我收到编译时错误。我是 Java 8 并发特性的新手,例如 CompletableFuture,我认为调用 thenRunAsync 将在不同的线程中运行每个 future1,future2,future3。调用thenRunAsync 是否正确?如果是,那么如何消除编译时错误?

但如果我这样做:

Stream.of(future1, future2, future3)
        .map(CompletableFuture::join)
        .collect(Collectors.toList());

它正在返回 List&lt;? extends List&lt;?&gt;&gt; 然后它似乎工作但我应该打电话给 .collect(Collectors.toList()) 吗?我不关心这个组合结果,因为每个单独的方法调用都已经用@Cacheable 进行了注释以用于缓存目的。 另外,如果我这样做:

Stream.of(future1, future2, future3)
        .foreach(CompletableFuture::join);

它会在不同的线程中运行每个future1,future2,future3 吗?如何在 3 个不同的线程中运行 future1,future2,future3? 有没有正确的方法来异步运行这三个数据库调用?

【问题讨论】:

  • 这些服务调用真的需要用CompletableFuture包装吗?
  • @andrew-s 不,最初这些方法返回List&lt;DTO&gt;。我已经将它们包装CompletableFuture 并将它们组合起来进行异步调用,不确定这是否正确
  • 澄清一下:为什么不只是service1.callMethod1()?为什么要包裹在CompletableFuture 中?也许this 也会有所帮助。
  • @andrew-s 正如我所说,根据我的有限知识,我已将它们包装在 CompletableFuture 以在不同的线程上调用它们,如果我这样做 service1.callMethod1() 那么它将在同一个线程上调用.

标签: java multithreading asynchronous java-8 completable-future


【解决方案1】:
CompletableFuture<List<DTO1> future1 = CompletableFuture.supplyAsync(() -> service1.callMethod1());
CompletableFuture<List<DTO2> future2 = CompletableFuture.supplyAsync(() -> service2.callMethod2());
CompletableFuture<List<DTO3> future3 = CompletableFuture.supplyAsync(() -> service3.callMethod3());

这段代码已经指示所有三个future 在不同的线程上运行(假设common pool 中至少有3 个线程)。在其中一个上调用 join() 只是指示调用线程在完成该任务时阻塞,并且不会改变 3 个调用并行进行的事实。您编译的所有解决方案都是合理的。

【讨论】:

  • 但是当调用join只是为了等待完成时,CompletableFuture.allOf(future1, future2, future3).join();比其他方法更简单。甚至future1.join(); future2.join(); future3.join(); 也可以……
猜你喜欢
  • 1970-01-01
  • 2023-02-25
  • 2019-01-24
  • 1970-01-01
  • 2019-08-25
  • 2021-12-25
  • 1970-01-01
  • 2014-07-28
  • 1970-01-01
相关资源
最近更新 更多