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

use*_*121 24 java concurrency multithreading completable-future

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);
Run Code Online (Sandbox Code Playgroud)

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

this.growSeedExecutor.shutdown();
this.growSeedExecutor.awaitTermination(1, TimeUnit.DAYS);
Run Code Online (Sandbox Code Playgroud)

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

CompletableFuture.allOf(this.growSeedFutureList).join();
Run Code Online (Sandbox Code Playgroud)

请让我知道推荐哪一个.

Did*_*r L 11

如果你真的想等待所有的期货,你可以简单地打电话给join()他们每个人:

growSeedFutureList.forEach(CompletableFuture::join);
Run Code Online (Sandbox Code Playgroud)

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

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

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

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


Ale*_*dov 10

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

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