java - 在 Java 中如何等待所有异步调用完成?
问题描述
概念上非常简单。我们有一个巨大的遗留 Java 站点,它不使用线程/异步。登录需要很长时间,因为它对不同的微服务进行了十几个调用,但每次都是同步的:每个都等待另一个完成,然后再进行下一次调用。然而,没有任何 API 调用取决于任何其他 API 调用的结果。
但我们确实需要在继续之前获得所有结果并将它们组合起来。很明显,我们应该能够并行进行这十几个调用,但要等待它们全部完成,以便在下一步中使用它们的数据。
所以在调用之前和之后一切都是同步的。但是,最好将它们各自并行地、异步地发送出去——或者只是并行地——然后我们只受到单个最慢调用的限制,而不是所有调用的总顺序时间。
我读过 Java 8 有一套很棒的新操作CompletableFuture
。但我还没有找到任何地方解释我的用途。我们不希望结果是一个承诺 - 我们很乐意等到它们全部完成然后继续。JS 有Promise.all()
,但即使这样也会返回一个承诺。
我能想到的就是在异步调用完成后稍等一下,只有在我们得到所有结果时才继续。这显然是疯了。
我在这里错过了什么吗?因为这对我来说似乎很明显,但似乎没有其他人对此有问题 - 否则方法是如此简单,没有人会费心去问,我就是不明白。
解决方案
如果我理解正确,你想要这样的东西:
ExecutorService executorService = Executors.newFixedThreadPool(4); // TODO: proper number of threads
Future<Integer> future1 = executorService.submit(() -> callService1()); // TODO: proper type and method
Future<String> future2 = executorService.submit(() -> callService2()); // TODO: proper type and method
executorService.shutdown();
executorService.awaitTermination(5, TimeUnit.MINUTES); // TODO: proper timeout
Integer result1 = future1.get(); // TODO: proper type
String result2 = future2.get(); // TODO: proper type
解释:
- 上面的代码创建了一个
ExecutorService
有 4 个线程的线程,您可以向其中提交所有任务(即调用微服务) - 然后你打电话
ExecutorService.shutdown
(不再允许提交任务)和ExecutorService.awaitTermination
(等到所有任务完成) - 最后,你调用
Future.get
所有的期货来得到结果- 请注意,如果任务在执行期间抛出异常,则调用
Future.get
将抛出一个ExecutionException
包装任务抛出的异常的
- 请注意,如果任务在执行期间抛出异常,则调用
推荐阅读
- user-interface - 如何分析 UWP 应用程序 UI 冻结?
- java - Android 中的 Firebase 事件记录离线和在线
- reactjs - reactjs如何在编辑表单中显示数据
- r - 用应用函数替换 for 循环
- reactjs - 多个 env 文件在 docker 上选择哪一个 - 创建反应应用程序
- ios - SDWebImage 不加载图像直到我在 Swift 中滚动 tableView
- r - 闪亮的模块:如何使用 DT::datatables 访问 selected_rows?
- authentication - 尝试使用 OAuth 端点进行授权时,我收到无效的同意请求 [Snowflake]
- c# - 在给定 Microsoft.Odata.Edm.IEdmModel 的情况下,如何确定绑定操作(函数或操作)所属的 EntitySet?
- google-apps-script - 应用程序脚本 - 在现有文件夹中创建新的谷歌文档