我们有一个异步方法:
public CompletableFuture<OlderCat> asyncGetOlderCat(String catName)给出一张猫的列表:
List<Cat> cats;我们想要创建一个批量操作,它将在cat名称和它的异步结果之间产生一个映射:
public CompletableFuture<Map<String, OlderCat>>我们还希望,如果从asyncGetOlderCat抛出异常,则不会将猫添加到地图中。
我们跟踪了this post和this one,并编写了以下代码:
List<Cat> cats = ...
Map<String, CompletableFuture<OlderCat>> completableFutures = cats
.stream()
.collect(Collectors.toMap(Cat::getName,
c -> asynceGetOlderCat(c.getName())
.exceptionally( ex -> /* null?? */ ))
));
CompletableFuture<Void> allFutures = CompletableFuture
.allOf(completableFutures.values().toArray(new CompletableFuture[completableFutures.size()]));
return allFutures.thenApply(future -> completableFutures.keySet().stream()
.map(CompletableFuture::join) ???
.collect(Collectors.toMap(????)));但目前还不清楚我们如何在allFutures中访问猫的名字,以及如何在OlderCat和catName之间进行匹配。
它能实现吗?
发布于 2019-06-06 20:12:27
你就快到了。您不需要将exceptionally()放在初始期货上,但应该在allOf()之后使用handle()而不是thenApply(),因为如果将来失败,allOf()也会失败。
在处理期货时,您可以从结果中筛选出失败的期货,并重新构建预期的映射:
Map<String, CompletableFuture<OlderCat>> completableFutures = cats
.stream()
.collect(toMap(Cat::getName, c -> asyncGetOlderCat(c.getName())));
CompletableFuture<Void> allFutures = CompletableFuture
.allOf(completableFutures.values().toArray(new CompletableFuture[0]));
return allFutures.handle((dummy, ex) ->
completableFutures.entrySet().stream()
.filter(entry -> !entry.getValue().isCompletedExceptionally())
.collect(toMap(Map.Entry::getKey, e -> e.getValue().join())));请注意,对join()的调用被保证是非阻塞的,因为thenApply()仅在所有期货完成后才会执行。
发布于 2019-06-06 19:18:09
据我所知,您需要的是包含所有结果的CompletableFuture,下面的代码正是您所需要的
public CompletableFuture<Map<String, OlderCat>> getOlderCats(List<Cat> cats) {
return CompletableFuture.supplyAsync(
() -> {
Map<String, CompletableFuture<OlderCat>> completableFutures = cats
.stream()
.collect(Collectors.toMap(Cat::getName,
c -> asyncGetOlderCat(c.getName())
.exceptionally(ex -> {
ex.printStackTrace();
// if exception happens - return null
// if you don't want null - save failed ones to separate list and process them separately
return null;
}))
);
return completableFutures
.entrySet()
.stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
e -> e.getValue().join()
));
}
);
}它在这里做什么-返回future,它在内部创建更多可完成的未来,并在结束时等待。
https://stackoverflow.com/questions/56475682
复制相似问题