什么是等待可完成的未来线程完成的推荐方法

我正在使用CompletableFuture ,如下面的代码所示。 但关于我应该等到所有可运行完成的方式,我找到了两种方法,我不知道它们之间的区别,哪一种是最佳实践? 它们如下:

代码

 this.growSeedFutureList = CompletableFuture.runAsync(new GrowSeedSERun(this.saliencyMat, this.seedXY, this.seedVal), this.growSeedExecutor); this.growSeedFutureList = CompletableFuture.runAsync(new GrowSeedNWRun(this.saliencyMat, this.seedXY, this.seedVal), this.growSeedExecutor); this.growSeedFutureList = CompletableFuture.runAsync(new GrowSeedNERun(this.saliencyMat, this.seedXY, this.seedVal), this.growSeedExecutor); this.growSeedFutureList = CompletableFuture.runAsync(new GrowSeedSWRun(this.saliencyMat, this.seedXY, this.seedVal), this.growSeedExecutor); 

第一种等待所有runnables完成的方法

 this.growSeedExecutor.shutdown(); this.growSeedExecutor.awaitTermination(1, TimeUnit.DAYS); 

等待所有runnables完成的第二种方法

 CompletableFuture.allOf(this.growSeedFutureList).join(); 

请让我知道推荐哪一个。

只有当执行程序(growSeedExecutor)仅用于给定任务时,这两种方式才是等效的。 第一种方式可能导致以下:另一个任务需要并行化,并为每个任务创建新的执行程序。 一些开发人员看到创建了太多执行程序,并决定使用单个通用执行程序,但未能删除所有执行程序关闭…

所以第二种方式(join())更可靠,因为它不那么复杂。 但是每个新的未来都应该添加到growSeedFutureList中,而不是分配给。

如果你真的想等待所有期货,你可以简单地在每个期货上调用join()

 growSeedFutureList.forEach(CompletableFuture::join); 

与使用allOf()相比,主要区别在于,一旦到达具有exception的未来,它将抛出exception,而allOf().join()版本将仅在所有期货完成后抛出exception(exception或不)。

另一个小的区别是,这并没有创建中间allOf阶段。 如果您想在所有期货完成后异步执行某些操作,而不是等待所有期货完成,那么此阶段仍然有用。

另一方面,执行程序的解决方案有几个缺点:

  • 它会阻止重用执行程序,因为它需要关闭它;
  • 它要求您对所有操作使用该执行程序 – 它不适用于以其他方式管理的CompletableFuture ;
  • 它没有清楚地表明你的意图,即等待所有的期货完成;
  • 实施起来比较复杂;
  • 它不处理exception完成 – 如果其中一个任务失败, awaitTermination()不会抛出任何exception。