如何在 Java 内等待所有异步调用完成?
How do you wait for all asynchronous calls to complete in Java?
概念上很简单。我们有一个巨大的遗留 java 站点,它不使用线程/异步。登录需要很长时间,因为它对不同的微服务进行了十几个调用,但一次都是同步的:每个都等待另一个完成,然后再进行下一个调用。但是,API 次调用中的 NONE 次调用取决于任何其他调用的结果。
但我们确实需要获得所有结果并在继续之前将它们组合起来。看起来很明显,我们应该能够并行进行这十几个调用,但要等待它们全部完成才能在下一步中使用它们的数据。
所以调用前后一切都是同步的。然而,最好将它们各自并行、异步地发送出去——或者只是并行地——然后我们只受到单个最慢调用的限制,而不是所有调用的总顺序时间。
我读到 Java 8 在 CompletableFuture
周围有一套很棒的新操作。但是我没有在任何地方找到我的使用说明。我们不希望结果成为承诺——我们很乐意等到它们全部完成后再继续。 JS 有 Promise.all()
,但即使是 returns 一个承诺。
我能想到的就是在异步调用完成后稍微等待一下,只有在我们获得所有结果后才继续。这显然是疯了。
我是不是漏掉了什么?因为这对我来说似乎很明显,但似乎没有其他人对此有任何问题 – 或者这种方法太简单了,没有人愿意问,我就是不明白。
如果我没理解错的话,你想要这样的东西:
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
解释:
- 以上代码创建了一个具有 4 个线程的
ExecutorService
,您可以向其提交所有任务(即调用微服务)
- 然后你调用
ExecutorService.shutdown
(no more task submissions allowed) and ExecutorService.awaitTermination
(等到所有任务完成)
- 最后,您对所有期货调用
Future.get
以获得结果
- 请注意,如果任务在执行期间抛出异常,对
Future.get
的调用将抛出一个 ExecutionException
来包装任务抛出的异常
概念上很简单。我们有一个巨大的遗留 java 站点,它不使用线程/异步。登录需要很长时间,因为它对不同的微服务进行了十几个调用,但一次都是同步的:每个都等待另一个完成,然后再进行下一个调用。但是,API 次调用中的 NONE 次调用取决于任何其他调用的结果。
但我们确实需要获得所有结果并在继续之前将它们组合起来。看起来很明显,我们应该能够并行进行这十几个调用,但要等待它们全部完成才能在下一步中使用它们的数据。
所以调用前后一切都是同步的。然而,最好将它们各自并行、异步地发送出去——或者只是并行地——然后我们只受到单个最慢调用的限制,而不是所有调用的总顺序时间。
我读到 Java 8 在 CompletableFuture
周围有一套很棒的新操作。但是我没有在任何地方找到我的使用说明。我们不希望结果成为承诺——我们很乐意等到它们全部完成后再继续。 JS 有 Promise.all()
,但即使是 returns 一个承诺。
我能想到的就是在异步调用完成后稍微等待一下,只有在我们获得所有结果后才继续。这显然是疯了。
我是不是漏掉了什么?因为这对我来说似乎很明显,但似乎没有其他人对此有任何问题 – 或者这种方法太简单了,没有人愿意问,我就是不明白。
如果我没理解错的话,你想要这样的东西:
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
解释:
- 以上代码创建了一个具有 4 个线程的
ExecutorService
,您可以向其提交所有任务(即调用微服务) - 然后你调用
ExecutorService.shutdown
(no more task submissions allowed) andExecutorService.awaitTermination
(等到所有任务完成) - 最后,您对所有期货调用
Future.get
以获得结果- 请注意,如果任务在执行期间抛出异常,对
Future.get
的调用将抛出一个ExecutionException
来包装任务抛出的异常
- 请注意,如果任务在执行期间抛出异常,对