completablefuture 的链式调用通过 thencombine 和 allof 分别解决双结果协同处理与多任务批量等待:thencombine 合并两个有逻辑关联的异步结果并执行 bifunction,allof 等待多个独立任务完成但不自动聚合结果,二者可组合构建含并行与串行的真实流水线。

CompletableFuture 的链式调用能力,核心在于把异步任务的“依赖关系”转化为可读、可组合、可错误隔离的代码结构。thenCombine 和 allOf 不是简单拼接,而是分别解决两类关键场景:两个有业务关联结果的协同处理,以及多个独立任务的批量等待与聚合。
thenCombine:合并两个有逻辑关联的异步结果
当你需要等两个异步操作都完成,并且用它们的结果共同计算出新值时,thenCombine 是最直接的选择。它接受另一个 CompletableFuture 和一个 BiFunction,这个函数会同时拿到两个 future 的结果。
- 必须确保两个 future 都成功完成,任一异常都会导致整个链失败(除非后续加 exceptionally)
- 回调函数在默认线程池中执行;如需指定线程,可用 thenCombineAsync 并传入 Executor
- 常见于“查用户信息 + 查订单列表 → 合并生成用户订单摘要”这类场景
allOf:等待全部完成,但不自动合并结果
allOf 接收一个 CompletableFuture[],返回一个新的 CompletableFuture
- 适合并行发起多个无依赖的 IO 请求(比如查 5 个不同服务的配置),只关心是否全成功,不关心中间值怎么组合
- 若任一 future 异常,allOf 返回的 future 也会以 CompletionException 包装抛出,需统一 handle 或提前捕获
- 想安全获取全部结果,推荐配合 stream().map(f -> f.join()).collect(...) 使用
组合使用:构建带分支与汇聚的真实流水线
真实业务中往往既有并行分支,又有串行依赖。例如:先并行拉取用户基础信息和最近三笔订单,再把两者结果交给下游服务做风控校验。
- 第一步用 supplyAsync 并行启动两个任务
- 第二步用 thenCombine 把两个结果组装成风控请求对象
- 第三步再用 thenCompose 提交风控请求(返回另一个 CompletableFuture),实现链式延伸
- 全程可插入 exceptionally 处理各环节异常,避免整条链崩断
线程池选择影响执行顺序和性能
默认使用 ForkJoinPool.commonPool(),但它的线程数等于 CPU 核数减 1(若大于 1 才启用)。IO 密集型任务容易因线程不足而阻塞。
- 建议为不同用途定义专用线程池:比如 ioPool 用于数据库/HTTP 调用,computePool 用于纯内存计算
- supplyAsync、thenCombineAsync 等带 Async 后缀的方法都支持传入自定义 Executor
- 避免在 thenApply 等无 Async 后缀方法里做耗时操作,否则会阻塞上游线程池










