java - 包装和转动单个 CompleteableFuture到具有 CompleteableFuture 结果的批量操作
问题描述
我们有一个异步方法:
public CompletableFuture<OlderCat> asyncGetOlderCat(String catName)
给定一个 Cats 列表:
List<Cat> cats;
我们喜欢创建一个批量操作,这将导致猫名与其异步结果之间的映射:
public CompletableFuture<Map<String, OlderCat>>
我们也喜欢如果从 中抛出异常asyncGetOlderCat
,则不会将猫添加到地图中。
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
& 之间匹配猫名。
可以实现吗?
解决方案
你快到了。你不需要exceptionally()
在最初的 futures 上加上 an ,但你应该在之后使用handle()
而不是,因为如果任何 future 失败, the will 也会失败。thenApply()
allOf()
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()
只有在所有期货完成后才会执行。
推荐阅读
- ruby-on-rails - 如何为 Rails 2.3.18 设置 puma 服务器
- python - 与 python 多处理相比,Python ray 代码的工作速度较慢
- javascript - 如何解析 JSON 文件以在 html 表格单元格中显示它的元素
- python - 如何根据python中的周数获取一周的所有日期
- python-3.x - 在 keras 中如何输入?
- javascript - 如何获取引导开关的值
- batch-file - 如何在 FOR /R 循环中排除 Windows 目录?
- angular - Viewchild 返回未定义
- sql - 如何切割长度未知的字符串的左侧部分?(带sql函数)
- oracle - Oracle:使用自动列表分区和范围子分区