我在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
)之前获取数据(fetchBazs
和getFoo
)。但是,我实际上将有两个以上。我目前有三个,但可能还会再增加一两个。我想并行运行所有初始调用,然后在全部完成后进行最终处理。
答案 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不太熟悉,因此可能会有更合适的解决方案。