Java 线程池(第十篇):(收官篇)CompletableFuture 异步编排实战 —— 多任务并行、结果汇总、超时控制与线程池协作

completableFuture 异步编排实战 —— 多任务并行、结果汇总、超时控制与线程池协作

如果说前 1–9 篇解决的是 “线程池如何安全、稳定地跑”
那么这一篇解决的是:

如何把多个异步任务“编排”成一个可读、可控、可维护的并发流程。

这正是现代 Java 并发从 ThreadPoolExecutor → CompletableFuture 的进化方向。

一、为什么需要 CompletableFuture?

先看一个你一定写过的代码:

Future<User> f1 = pool.submit(() -> this.loadUser()); Future<User> f2 = pool.submit(() -> this.loadUser()); User user = f1.get(); Order order = f2.get(); 

问题很明显:

  • get() 阻塞
  • 顺序代码读起来像同步
  • 异常处理零散
  • 任务依赖一多,代码迅速失控

CompletableFuture 的核心价值只有一句话:

用“声明式”的方式,描述异步任务之间的关系,而不是用 get() 等结果。

二、CompletableFuture 和线程池的关系(先搞清楚)

1️⃣ CompletableFuture ≠ 线程池

  • CompletableFuture 是 异步任务编排工具
  • 线程池是 执行引擎

2️⃣ 默认线程池是 ForkJoinPool(不推荐直接用)

CompletableFuture.supplyAsync(() -> work()); 

默认使用:

ForkJoinPool.commonPool() 

👉 生产环境强烈建议:显式传入你自己的线程池(第五篇)

CompletableFuture.supplyAsync(() -> work(), ioPool); 

三、最核心的三种编排模式(80% 场景)

1️⃣ thenApply —— 单任务链式变换

CompletableFuture .supplyAsync(() -> 1, pool) .thenApply(x -> x + 1) .thenApply(x -> x * 2) .thenAccept(System.out::println); 
  • 同一条任务链
  • 上一步完成 → 执行下一步
  • 适合 数据转换

2️⃣ thenCompose —— 依赖型异步(避免嵌套)

CompletableFuture<User> f = loadUserAsync(id) .thenCompose(user -> loadProfileAsync(user)); 

等价于(但比它优雅得多):

CompletableFuture<User> f = loadUserAsync(id) .thenApply(user -> loadProfileAsync(user)) .get(); // ❌ 

一句话:

thenCompose = “异步版的 flatMap”

3️⃣ thenCombine —— 并行任务结果合并(非常常用)

CompletableFuture<User> userFuture = loadUserAsync(id); CompletableFuture<Order> orderFuture = loadOrderAsync(id); CompletableFuture<UserInfo> result = userFuture.thenCombine(orderFuture, (user, order) -> new UserInfo(user, order)); 

✔ 并行执行
✔ 都完成后才合并
✔ 没有 get()

四、allOf / anyOf:真正的“并行编排”

allOf:全部完成

CompletableFuture<Void> all = CompletableFuture.allOf(f1, f2, f3); all.thenRun(() -> System.out.println("all done")); 

⚠ 注意:allOf 不帮你收集结果,你需要自己 get(或 join)

List<Result> results = List.of(f1, f2, f3) .stream() .map(CompletableFuture::join) .toList(); 

anyOf:任意一个完成

CompletableFuture<Void> all = CompletableFuture.allOf(f1, f2, f3); all.thenRun(() -> System.out.println("all done")); 

⚠ 注意:allOf 不帮你收集结果,你需要自己 get(或 join)

List<Result> results = List.of(f1, f2, f3) .stream() .map(CompletableFuture::join) .toList(); 

anyOf:任意一个完成

CompletableFuture<Object> any = CompletableFuture.anyOf(f1, f2); any.thenAccept(r -> System.out.println("first = " + r)); 

常用于:

  • 多数据源兜底
  • 多节点竞速

五、异常处理:这是 CompletableFuture 的强项

1️⃣ exceptionally —— 兜底恢复

CompletableFuture .supplyAsync(() -> risky(), pool) .exceptionally(e -> { log.error("error", e); return defaultValue; }); 

2️⃣ handle —— 成功 / 失败都处理

future.handle((r, e) -> { if (e != null) { return fallback; } return r; }); 

一句工程经验:

CompletableFuture 的异常是“流的一部分”,不是打断流程。

六、超时控制(非常关键)

Java 9+ 推荐方式

future .orTimeout(2, TimeUnit.SECONDS) .exceptionally(e -> fallback); 

或者:

future .completeOnTimeout(fallback, 2, TimeUnit.SECONDS); 

比 Future.get(timeout) 的优势:

  • 不阻塞线程
  • 超时是异步语义的一部分

七、CompletableFuture + 线程池的最佳实践

✔ 1)明确线程池职责

  • IO 任务 → ioPool
  • CPU 任务 → cpuPool
  • 定时 → scheduledPool

CompletableFuture.supplyAsync(this::loadData, ioPool)

✔ 2)不要在 CompletableFuture 里 get()

// ❌ 反模式 future.thenApply(r -> anotherFuture.get()); 

✔ 3)异常必须收敛在链路末端

future .thenApply(...) .thenApply(...) .exceptionally(this::fallback); 

✔ 4)避免在 commonPool 跑重任务

ForkJoinPool 是共享资源,容易拖垮 JVM。

八、一个完整实战 Demo

补充知识点:

Java 的“高阶函数”到底是什么:Runnable / Callable 就是函数参数

CompletableFuture<User> userFuture = CompletableFuture.supplyAsync(this::loadUser, ioPool); CompletableFuture<Order> orderFuture = CompletableFuture.supplyAsync(this::loadOrder, ioPool); CompletableFuture<UserInfo> result = userFuture .thenCombine(orderFuture, UserInfo::new) .orTimeout(2, TimeUnit.SECONDS) .exceptionally(e -> { log.error("timeout or error", e); return UserInfo.empty(); }); result.thenAccept(info -> render(info)); 

这个 Demo 覆盖了:

  • 并行
  • 合并
  • 超时
  • 异常
  • 自定义线程池

九、和前 9 篇的“闭环关系”

你现在拥有的是一套完整体系:

  • 线程池(1–5)
  • 任务提交与异常(6–7)
  • 可观测性(8)
  • 背压(9)
  • 异步编排(10) ← 收官

一句总结:

ThreadPoolExecutor 决定“系统能不能跑”,
CompletableFuture 决定“并发代码能不能写得优雅、可维护”。

十、全专栏终极总结

线程池是并发执行的基础设施背压决定系统是否稳定监控决定问题是否可见CompletableFuture 决定异步逻辑是否可维护并发不是“多开线程”,而是“正确组织任务关系”

到这里,已经是一个完整、工程级、的体系。

Read more

【记录】Copilot|Github Copilot重新学生认证通过方法(2025年7月,包括2FA和认证材料、Why are you not on campus)

【记录】Copilot|Github Copilot重新学生认证通过方法(2025年7月,包括2FA和认证材料、Why are you not on campus)

文章目录 * 前言 * 步骤 * 最重要的一步 前言 事实上,Github Copilot马上就要开源了,我原本的认证过期了。但是在我体验了众多的代码补全工具实在是太难用了之后,我觉得一天也等不了了,就去再一次认证了学生认证。 这次严格了很多,要求巨无敌多,这里写一下新认证要干的事情。 一口气认证了八次的含金量谁懂,把要踩的坑全踩完了。。 步骤 (如果你是第一次认证还要额外添加一下自己的学校邮箱,这里我就略过不提了) 在所有的步骤之前,最好确保你的本人就在学校或者在学校附近。当你出现了报错You appear not to be near any campus location for the school you have selected.时,会非常难通过。 而其他的报错可以按我下文这种方式通过。 (对于部分学校,比如华科大)双重认证Two-factor authentication要打开:跳转这个网站https://github.com/settings/security,然后点下一步开启认证,

By Ne0inhk

服务器环境 VsCode:Github Copilot 安装完成却用不了?关键步骤补全

GitHub Copilot在VS Code中无法使用的关键解决步骤 1. 基础环境检查 * VS Code版本:确保使用最新版(至少≥1.60),旧版可能导致兼容问题 * Copilot状态:在VS Code左侧活动栏点击Copilot图标(飞机形状),检查是否显示已登录和启用状态 * 网络环境:Copilot需访问GitHub服务器,尝试关闭代理或检查防火墙是否屏蔽api.github.com 2. 核心配置步骤 # 步骤1:检查Copilot是否激活 # 在VS Code命令面板(Ctrl+Shift+P)输入: > GitHub Copilot: Check Status # 步骤2:重置授权令牌(常见问题根源) > GitHub Copilot: Reset GitHub Copilot Token # 步骤3:强制刷新扩展 >

By Ne0inhk
【AIGC】冷启动数据与多阶段训练在 DeepSeek 中的作用

【AIGC】冷启动数据与多阶段训练在 DeepSeek 中的作用

博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳]本文专栏: AIGC |ChatGPT 文章目录 * 💯前言 * 💯冷启动数据的作用 * 冷启动数据设计 * 💯多阶段训练的作用 * 阶段 1:冷启动微调 * 阶段 2:推理导向强化学习(RL) * 阶段 3:拒绝采样与监督微调(SFT) * 阶段 4:多场景强化学习 * 💯代码示例:冷启动数据与多阶段训练的实现 * 1. 冷启动微调阶段 * 作用与应用: * 2. 推理导向的强化学习阶段 * 作用与应用: * 3. 拒绝采样与监督微调阶段 * 作用与应用: * 4. 多场景强化学习 * 作用与应用: * 总体流程 * DeepSeek 中的应用 * 💯总结 💯前言 在人工智能领域,深度学习模型的训练和优化往往需要大量的标注数据和计算资源。然而,面对复杂任务时,即使是最先进的技术和大量的训练数据也未必能够保证模型的最优表现。DeepSeek

By Ne0inhk

Qwen3-Reranker部署教程(CI/CD集成):GitHub Actions自动发布

Qwen3-Reranker部署教程(CI/CD集成):GitHub Actions自动发布 1. 项目概述与核心价值 Qwen3-Reranker是一个基于Qwen3-Reranker-0.6B大模型的语义重排序Web工具,专门用于提升RAG(检索增强生成)系统的精度和效果。这个工具能够深度理解查询词与候选文档之间的语义相关性,并通过直观的可视化界面展示排序结果。 在实际的搜索和问答系统中,传统的向量检索可能会返回一些看似相关但实际上语义匹配度不高的结果。Qwen3-Reranker通过深度语义匹配技术,对这些候选结果进行精细排序,确保最相关的内容被优先展示,从而显著提升最终生成答案的质量。 核心优势: * 精准的语义理解能力,比传统方法更能捕获语境信息 * 轻量化设计,0.6B版本在保证效果的同时兼顾部署效率 * 友好的Web界面,无需编码经验即可使用 * 自动化部署流程,支持持续集成和快速迭代 2. 环境准备与基础配置 在开始部署之前,需要确保你的开发环境满足以下要求: 2.1 系统要求 * Python 3.8或更高版本 * 至少8GB内存(推

By Ne0inhk