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

新手上路,请多包涵

我正在使用 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);

等待所有可运行对象完成的第一种方法

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

等待所有可运行对象完成的第二种方法

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

请告诉我推荐哪一个。

原文由 user2121 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 356
2 个回答

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

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

原文由 Alexei Kaigorodov 发布,翻译遵循 CC BY-SA 3.0 许可协议

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

 growSeedFutureList.forEach(CompletableFuture::join);

与使用 allOf() 相比的主要区别在于,一旦它到达 future completed with exception 就会抛出异常,而 allOf().join() 版本只会在所有 futures 之后抛出异常已经完成(例外或不)。

另一个小区别是,这不会创建中介 allOf 阶段。如果您想在所有 futures 完成后异步执行某些操作,而不是仅仅等待所有 futures 完成,这样的阶段仍然有用。

执行者在另一边的解决方案有几个缺点:

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

原文由 Didier L 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题