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



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

请告诉我推荐哪一个

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

growSeedFutureList.forEach(CompletableFuture::join);

与使用allOf()相比的主要区别是,它将在到达一个异常完成的未来时抛出一个异常,而allOf().join()版本只会在所有未来完成(异常或非异常)后抛出一个异常。

另一个小区别是,这不会创建中间的allOf阶段。如果你想在所有的期货都完成后异步地做一些事情,而不是等待所有的期货都完成,那么这个阶段仍然是有用的。

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

  • 它阻止重用执行器,因为它需要关闭执行器;
  • 它要求你在所有的操作中使用这个执行器——它不能和其他方式管理的CompletableFuture一起工作;
  • 它没有清楚地显示你的意图,这是等待所有期货完成;
  • 实现起来比较复杂;
  • 它不处理异常完成-如果其中一个任务失败,awaitTermination()不会抛出异常。

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

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

回复有点晚了,但希望这个代码能帮助别人寻找。它使用了常见的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);
    }
}

最新更新