我有一个问题 stream().forEach
在方法返回之前,它没有及时完成,这是怎么回事。
我的实体:
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Foo {
private String a;
private int b;
private int c;
private String d;
private String e;
}
我有一个方法,它调用一个外部服务,该服务得到一个列表 Foo
然后对于该列表中的每个成员,它调用另外两个外部服务来填写 d
和 e
字段。
public List<Foo> getOrdresListe() {
Foo[] fooArray = externalServiceOne.getFooList();
Arrays.stream(fooArray).forEach((f) -> {
CompletableFuture.supplyAsync(AsyncUtils.supplierWithCustomDependencies(() -> {
Dob dob = externalServiceTwo.getDeeEntity(f.getA());
f.setD(dob.getD());
Efo efo = externalServiceThree.getEeeEntity(f.getA());
f.setE(efo.getE());
return f;
}));
});
List<Foo> fooList = Arrays.asList(fooArray);
return fooList; // when this statement is reached d and e fields are null.
}
由于一些性能问题(和一些最佳实践),我将 externalServiceTwo.getDeeEntity
和 externalServiceThree.getEeeEntity
异步地与一个自定义的供应商在调用服务时嵌入一些依赖关系。但主要问题是,当返回 fooList
d
和 e
字段为空。
我的问题是如何等待所有异步执行结束后再返回 fooList
?
你为什么不创建所有的 CompletableFuture
s作为中间操作,并在终端操作中等待所有异步执行完成。
Arrays.stream(fooArray).map((f) -> CompletableFuture.supplyAsync(AsyncUtils.supplierWithCustomDependencies(() -> {
Dob dob = externalServiceTwo.getDeeEntity(f.getA());
f.setD(dob.getD());
Efo efo = externalServiceThree.getEeeEntity(f.getA());
f.setE(efo.getE());
return f;
})
)).forEach(fooCompletableFuture -> {
try {
fooCompletableFuture.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
});
你可以直接记住这些异步任务,然后手动等待它们的完成。
public List<Foo> getOrdresListe() {
Foo[] fooArray = externalServiceOne.getFooList();
final List<CompletableFuture<Foo>> futures = new ArrayList<>(); // remember each
Arrays.stream(fooArray).forEach((f) -> {
futures.add(CompletableFuture.supplyAsync(
AsyncUtils.supplierWithCustomDependencies(() -> {
Dob dob = externalServiceTwo.getDeeEntity(f.getA());
f.setD(dob.getD());
Efo efo = externalServiceThree.getEeeEntity(f.getA());
f.setE(efo.getE());
return f;
})));
});
for (CompletableFuture<Foo> future : futures) {
future.join(); // wait for each
}
List<Foo> fooList = Arrays.asList(fooArray);
return fooList;
}