如何在CompletableFuture.allOf

时间:2018-12-03 21:43:22

标签: java java-8 completable-future

我在Java中有一个异步函数。我想对多个API进行异步调用(并行),然后创建响应。由于我需要不同的结果,因此我将其保存在类中。我具有帮助程序函数来调用外部API(具有返回CompletableFuture<List<T>>的调用函数的类)。我可以这样:

public class MyAction{
   private List<Bar> bars;
   private List<Baz> bazs;

   public CompletableFuture<Foo> run() {
       CompletableFuture<Void> fetchBars = new BarFetcher().call().thenAccept(this::populateBars);
       CompletableFuture<Void> fetchBazs = new BazFetcher().call().thenAccept(this::populateBazs);

       return CompletableFuture.allOf(fetchBars, fetchBazs).thenApply(this::getFoo);
   }

   private void populateBars(final List<Bar> bars) {
       this.bars = bars;
   }

   private void populateBaz(final List<Baz> bazs) {
       this.bazs = bazs;
   }

   private Foo getFoo(final Void dummy) {
       return new Foo(bars, bazs);
   }
}

但是我必须在final Void dummy函数中添加不必要的参数(getFoo)才能使其正常工作。我可以避免吗?如果实际上应该只是getFoo()而不是getFoo(final Void dummy)。有什么方法可以等待多个期货完成,然后在不直接传递任何数据的情况下链接另一个函数?

注意:该示例只有两个初始调用,以便在最终处理(fetchbars)之前获取数据(fetchBazsgetFoo)。但是,我实际上将有两个以上。我目前有三个,但可能还会再增加一两个。我想并行运行所有初始调用,然后在全部完成后进行最终处理。

2 个答案:

答案 0 :(得分:2)

使用正确的工具进行作业。要合并两个期货,只需使用

public CompletableFuture<Foo> run() {
    return new BarFetcher().call().thenCombine(new BazFetcher().call(),
        (List<Bar> bars, List<Baz> bazs) -> new Foo(bars, bazs));
}

或更简单

public CompletableFuture<Foo> run() {
    return new BarFetcher().call().thenCombine(new BazFetcher().call(), Foo::new);
}

答案 1 :(得分:0)

您可以如下更改对lambda的方法引用的使用:

return CompletableFuture.allOf(fetchBars, fetchBazs)
                        .thenApply(e -> getFoo());

那么您不必引入虚拟参数。


请注意,我对CompletableFuture API不太熟悉,因此可能会有更合适的解决方案。