等待可完成的未来线程完成的推荐方法是什么
What is the recommended way to wait till the Completable future threads finish
我正在使用 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();
请告诉我推荐哪一个。
仅当执行器(growSeedExecutor)仅用于给定任务时,两种方式才等效。第一种方式可能会导致以下情况:另一个任务需要并行化,并且为每个任务创建新的执行器。一些开发人员看到创建了太多执行器,并决定使用单个通用执行器,但未能删除所有执行器关闭...
所以第二种方法 (join()) 更可靠,因为它不那么复杂。但是每个新的future都应该添加到growSeedFutureList中,而不是赋值给。
如果你真的想等待所有的期货,你可以简单地对它们中的每一个调用 join()
:
growSeedFutureList.forEach(CompletableFuture::join);
与使用 allOf()
相比的主要区别在于,一旦到达 future completed with exception 就会抛出异常,而 allOf().join()
版本毕竟只会抛出异常期货已经完成(有无例外)。
另一个小区别是这不会创建中间 allOf
阶段。如果您想在所有 futures 完成后异步执行某些操作,而不是仅仅等待所有 futures 完成,这样的阶段仍然有用。
执行者在另一边的解决方案有几个缺点:
- 它阻止重用执行程序,因为它需要关闭;
- 它要求您对所有操作使用该执行器——它不适用于以其他方式管理的
CompletableFuture
;
- 它没有清楚地表明您的意图,即等待所有期货完成;
- 实现起来比较复杂;
- 它不处理异常完成——如果其中一项任务失败,
awaitTermination()
不会抛出异常。
回复有点晚了,但希望这段代码对寻找的人有所帮助。这使用常见的 forkJoin 池执行器
package com.company;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
public class CompletableFutureExample {
public static void main(String args[]){
List<CompletableFuture> futureList=new ArrayList<>();
for(int i=0;i<10;i++) {
futureList.add(CompletableFuture.supplyAsync(()->getThreadName()).thenAccept(name->printThreadName(name)));
}
futureList.forEach(CompletableFuture::join);
}
static String getThreadName(){
String threadDetails=Thread.currentThread().getName();
System.out.println("thread deteails::::"+threadDetails);
return threadDetails;
}
static void printThreadName(String value){
System.out.println("thread string value::"+value);
}
}
我正在使用 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();
请告诉我推荐哪一个。
仅当执行器(growSeedExecutor)仅用于给定任务时,两种方式才等效。第一种方式可能会导致以下情况:另一个任务需要并行化,并且为每个任务创建新的执行器。一些开发人员看到创建了太多执行器,并决定使用单个通用执行器,但未能删除所有执行器关闭...
所以第二种方法 (join()) 更可靠,因为它不那么复杂。但是每个新的future都应该添加到growSeedFutureList中,而不是赋值给。
如果你真的想等待所有的期货,你可以简单地对它们中的每一个调用 join()
:
growSeedFutureList.forEach(CompletableFuture::join);
与使用 allOf()
相比的主要区别在于,一旦到达 future completed with exception 就会抛出异常,而 allOf().join()
版本毕竟只会抛出异常期货已经完成(有无例外)。
另一个小区别是这不会创建中间 allOf
阶段。如果您想在所有 futures 完成后异步执行某些操作,而不是仅仅等待所有 futures 完成,这样的阶段仍然有用。
执行者在另一边的解决方案有几个缺点:
- 它阻止重用执行程序,因为它需要关闭;
- 它要求您对所有操作使用该执行器——它不适用于以其他方式管理的
CompletableFuture
; - 它没有清楚地表明您的意图,即等待所有期货完成;
- 实现起来比较复杂;
- 它不处理异常完成——如果其中一项任务失败,
awaitTermination()
不会抛出异常。
回复有点晚了,但希望这段代码对寻找的人有所帮助。这使用常见的 forkJoin 池执行器
package com.company;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
public class CompletableFutureExample {
public static void main(String args[]){
List<CompletableFuture> futureList=new ArrayList<>();
for(int i=0;i<10;i++) {
futureList.add(CompletableFuture.supplyAsync(()->getThreadName()).thenAccept(name->printThreadName(name)));
}
futureList.forEach(CompletableFuture::join);
}
static String getThreadName(){
String threadDetails=Thread.currentThread().getName();
System.out.println("thread deteails::::"+threadDetails);
return threadDetails;
}
static void printThreadName(String value){
System.out.println("thread string value::"+value);
}
}