发布于2026-06-16 阅读(0)
扫一扫,手机访问
Ja va 并发编程的演进,活脱脱就是一部异步任务处理方式的升级史。不妨回想一下各个阶段的核心痛点:

Thread / Runnable(JDK 1.0)
↓ 痛点:无返回值、难以管理
Future + Callable(JDK 5)
↓ 痛点:get() 阻塞、无法链式组合
CompletableFuture(JDK 8)✅
↓ 优势:非阻塞、链式调用、函数式编排
可以说,CompletableFuture 是 JDK 8 为异步编程给出的终极方案。它精准地击碎了传统 Future 的几大软肋:
future.get() 死等结果的尴尬thenApply → thenAccept → thenRun,流水线一样组织代码allOf / anyOf 就能搞定多个异步任务的协同exceptionally / handle 让异常捕获变得优雅先看一眼整体结构图,心里有个谱。
┌─────────────────────────────┐
│ 创建 CompletableFuture │
└──────────┬──────────────────┘
│
┌────────────────┼────────────────┐
▼ ▼ ▼
supplyAsync(U) runAsync() completedFuture(U)
(有返回值) (无返回值) (立即完成)
│
┌────────────────────┼────────────────────┐
▼ ▼ ▼
┌─────────────┐ ┌──────────────┐ ┌────────────────┐
│ 转换类方法 │ │ 消费类方法 │ │ 组合类方法 │
├─────────────┤ ├──────────────┤ ├────────────────┤
│thenApply │ │thenAccept │ │thenCombine │
│thenCompose │ │thenRun │ │thenAcceptBoth │
│applyToEither│ │acceptEither │ │runAfterBoth │
│handle │ │whenComplete │ │runAfterEither │
└─────────────┘ └──────────────┘ └────────────────┘
│ │
▼ ▼
┌─────────────┐ ┌────────────────┐
│ 异常处理 │ ┌──────────────►│ 多任务组合 │
├─────────────┤ │ ├────────────────┤
│exceptionally│ │ │allOf(全部完成) │
│handle │ │ │anyOf(任一完成) │
│whenComplete │ │ └────────────────┘
└─────────────┘ │
▼
┌─────────────┐
│ 获取结果 │
├─────────────┤
│get() │
│get(timeout) │
│join() │
│orTimeout() │
│completeOnTimeout()
└─────────────┘
// 基础用法:使用默认 ForkJoinPool CompletableFuturefuture = CompletableFuture.supplyAsync(() -> { // 模拟耗时操作,比如远程 API 调用 try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } return "Hello, CompletableFuture!"; }); // 非阻塞获取结果 String result = future.join(); // join() 不抛检查异常 System.out.println(result); // Hello, CompletableFuture!
// 执行一个不需要返回值的异步操作 CompletableFuturefuture = CompletableFuture.runAsync(() -> { System.out.println("执行异步任务: " + Thread.currentThread().getName()); // 发邮件、写日志,诸如此类 }); future.join(); // 等它跑完
// ⚠️ 默认用的是 ForkJoinPool.commonPool(),生产环境真心建议指定线程池 ExecutorService executor = Executors.newFixedThreadPool(4); CompletableFuturefuture = CompletableFuture.supplyAsync(() -> { System.out.println("线程: " + Thread.currentThread().getName()); return "使用自定义线程池"; }, executor); // 别忘关线程池 executor.shutdown();
⚠️ 重要提醒:默认的
ForkJoinPool.commonPool()是全局共享的。一旦某个任务阻塞或耗时过长,其他组件也会跟着遭殃。生产环境务必传入自定义 Executor。
这才是最能体现 CompletableFuture 魅力的地方,一段流水线下来,代码干净利落。
CompletableFutureresult = CompletableFuture.supplyAsync(() -> 10) .thenApply(x -> x * 2) // 20:结果翻倍 .thenApply(x -> x + 5); // 25:再加 5 System.out.println(result.join()); // 25
CompletableFuture.supplyAsync(() -> "World")
.thenAccept(s -> System.out.println("Hello, " + s));
// 输出: Hello, World
CompletableFuture.supplyAsync(() -> {
// 复杂计算过后...
return "done";
}).thenRun(() -> {
System.out.println("任务已完成!清理资源...");
});
// 典型的场景:第一个异步任务的结果,是第二个异步任务的输入 CompletableFutureuserId = CompletableFuture.supplyAsync(() -> "user_123"); CompletableFuture userInfo = userId.thenCompose(id -> CompletableFuture.supplyAsync(() -> { // 拿 id 去查用户详情,模拟 RPC 调用 return "用户" + id + ": 张三, age=28"; }) ); System.out.println(userInfo.join()); // 用户user_123: 张三, age=28
thenApply vs thenCompose 的区别:
| 方法 | 返回值 | 适用场景 |
|---|---|---|
thenApply | CompletableFuture | 同步转换,类似 Stream.map |
thenCompose | CompletableFuture → 扁平化 | 异步嵌套,类似 Stream.flatMap |
CompletableFuturepriceFuture = CompletableFuture.supplyAsync(() -> 99.9); CompletableFuture quantityFuture = CompletableFuture.supplyAsync(() -> 3); // 两个都跑完,算总价 CompletableFuture totalFuture = priceFuture.thenCombine( quantityFuture, (price, qty) -> price * qty ); System.out.printf("总价: %.2f 元%n", totalFuture.join()); // 总价: 299.70 元
CompletableFuturetask1 = CompletableFuture.supplyAsync(() -> { sleep(500); return "任务1完成"; }); CompletableFuture task2 = CompletableFuture.supplyAsync(() -> { sleep(300); return "任务2完成"; }); CompletableFuture task3 = CompletableFuture.supplyAsync(() -> { sleep(700); return "任务3完成"; }); // 等所有都搞定了再触发 CompletableFuture allDone = CompletableFuture.allOf(task1, task2, task3); allDone.thenRun(() -> { System.out.println(task1.join()); // 任务1完成 System.out.println(task2.join()); // 任务2完成 System.out.println(task3.join()); // 任务3完成 System.out.println("✅ 全部任务执行完毕!"); }).join();
CompletableFuturefastTask = CompletableFuture.supplyAsync(() -> { sleep(200); return "快速任务"; }); CompletableFuture slowTask = CompletableFuture.supplyAsync(() -> { sleep(2000); return "慢速任务" }); // 谁先完成就拿谁的结果 Object firstResult = CompletableFuture.anyOf(fastTask, slowTask).join(); System.out.println("最快完成的: " + firstResult); // 快速任务
代码里的异常迟早要来,与其被动等待,不如主动规划。
CompletableFuturefuture = CompletableFuture.supplyAsync(() -> { if (true) throw new RuntimeException("模拟异常!"); return "正常结果"; }).exceptionally(ex -> { System.err.println("捕获到异常: " + ex.getMessage()); return "降级默认值"; // 给一个兜底数据 }); System.out.println(future.join()); // 降级默认值
CompletableFuture.supplyAsync(() -> {
// 可能抛异常的操作
int result = 10 / 0;
return "成功: " + result;
}).handle((result, ex) -> {
if (ex != null) {
System.err.println("发生错误: " + ex.getMessage());
return "错误处理后的默认响应";
}
return "处理成功: " + result;
}).thenAccept(System.out::println);
CompletableFuture.supplyAsync(() -> "重要数据")
.whenComplete((result, ex) -> {
// 无论成功失败都会执行,适合日志记录、指标上报
if (ex != null) {
System.err.println("任务失败,记录日志");
} else {
System.out.println("任务成功,耗时统计...");
}
// 注意:不返回新值,不会改变原始结果
});
| 方法 | 触发时机 | 能否恢复 | 能否改变结果 |
|---|---|---|---|
exceptionally | 仅异常时 | ✅ 返回替代值 | ✅ |
handle | 正常+异常时 | ✅ 返回新值 | ✅ |
whenComplete | 正常+异常时 | ❌ 仅副作用 | ❌ |
// JDK 9+ 引入的 orTimeout CompletableFuturefutureWithTimeout = CompletableFuture.supplyAsync(() -> { sleep(5000); // 模拟一个耗时 5 秒的任务 return "结果"; }).orTimeout(2, TimeUnit.SECONDS) // 最多等 2 秒 .exceptionally(ex -> { if (ex instanceof TimeoutException) { return "超时降级结果"; } return "其他异常"; }); // 而 completeOnTimeout 更温和,超时不抛异常,直接返回默认值 CompletableFuture safeFuture = CompletableFuture.supplyAsync(() -> { sleep(5000); return "真实结果"; }).completeOnTimeout("默认超时值", 2, TimeUnit.SECONDS);
先看一个活生生的例子:电商商品详情页的数据聚合,相信不少同行对此深有体会。从多个微服务并行拉取数据再组装成响应,这正是 CompletableFuture 的拿手好戏。
import ja va.util.*;
import ja va.util.concurrent.*;
public class EcommerceDetailAggregator {
// 模拟各个微服务
private static CompletableFuture fetchProduct(String productId) {
return CompletableFuture.supplyAsync(() -> {
sleep(300);
return new ProductInfo(productId, "MacBook Pro 16寸", 18999.00);
});
}
private static CompletableFuture> fetchReviews(String productId) {
return CompletableFuture.supplyAsync(() -> {
sleep(400);
return Arrays.asList(
new Review("用户A", "性能强劲,开发利器!", 5),
new Review("用户B", "屏幕素质顶级", 5),
new Review("用户C", "略重但可以接受", 4)
);
});
}
private static CompletableFuture fetchInventory(String productId) {
return CompletableFuture.supplyAsync(() -> {
sleep(200);
return new Inventory(productId, 128, "北京仓");
});
}
private static CompletableFuture> fetchRecommendations(String productId) {
return CompletableFuture.supplyAsync(() -> {
sleep(350);
return Arrays.asList(
new Recommendation("Magic Mouse", 699),
new Recommendation("USB-C Hub", 259)
);
});
}
public static void main(String[] args) {
String productId = "P20240614";
long startTime = System.currentTimeMillis();
// 1. 并行发起 4 个异步请求
CompletableFuture productFuture = fetchProduct(productId);
CompletableFuture> reviewsFuture = fetchReviews(productId);
CompletableFuture inventoryFuture = fetchInventory(productId);
CompletableFuture> recsFuture = fetchRecommendations(productId);
// 2. 组装最终结果
CompletableFuture pageData = productFuture
.thenCombine(reviewsFuture, (product, reviews) -> {
PageResponse resp = new PageResponse();
resp.product = product;
resp.reviews = reviews;
return resp;
})
.thenCombine(inventoryFuture, (resp, inventory) -> {
resp.inventory = inventory;
return resp;
})
.thenCombine(recsFuture, (resp, recs) -> {
resp.recommendations = recs;
return resp;
});
// 3. 设置超时 + 异常处理
pageData = pageData.orTimeout(3, TimeUnit.SECONDS)
.exceptionally(ex -> {
System.err.println("聚合超时或异常: " + ex.getMessage());
return PageResponse.fallback();
});
// 4. 输出结果
PageResponse response = pageData.join();
long elapsed = System.currentTimeMillis() - startTime;
System.out.println("n========== 商品详情页响应 ==========");
System.out.println("? 商品: " + response.product.name);
System.out.println("? 价格: ¥" + response.product.price);
System.out.println("? 库存: " + response.inventory.stock + "件 (" + response.inventory.warehouse + ")");
System.out.println("⭐ 评分: " + a vgRating(response.reviews));
System.out.println("? 推荐: " + formatRecs(response.recommendations));
System.out.println("⏱️ 总耗时: " + elapsed + "ms(串行需~1250ms)");
System.out.println("======================================n");
}
// ========== 辅助方法 ==========
private static void sleep(long ms) {
try { Thread.sleep(ms); } catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
private static double a vgRating(List reviews) {
return reviews.stream().mapToInt(r -> r.rating).a verage().orElse(0);
}
private static String formatRecs(List recs) {
StringBuilder sb = new StringBuilder();
for (Recommendation r : recs) sb.append(r.name).append("(¥").append(r.price).append(") ");
return sb.toString().trim();
}
// ========== 数据模型 ==========
static class ProductInfo { String id, name; double price;
ProductInfo(String id, String name, double price) { this.id=id; this.name=name; this.price=price; } }
static class Review { String user, comment; int rating;
Review(String user, String comment, int rating) { this.user=user; this.comment=comment; this.rating=rating; } }
static class Inventory { String productId, warehouse; int stock;
Inventory(String pid, int stock, String wh) { this.productId=pid; this.stock=stock; this.warehouse=wh; } }
static class Recommendation { String name; double price;
Recommendation(String name, double price) { this.name=name; this.price=price; } }
static class PageResponse {
ProductInfo product; List reviews; Inventory inventory; List recommendations;
static PageResponse fallback() { PageResponse r = new PageResponse(); r.product = new ProductInfo("", "暂不可用", 0); return r; }
}
}
预期输出:
========== 商品详情页响应 ==========
? 商品: MacBook Pro 16寸
? 价格: ¥18999.0
? 库存: 128件 (北京仓)
⭐ 评分: 4.67
? 推荐: Magic Mouse(¥699.0) USB-C Hub(¥259.0)
⏱️ 总耗时: ~420ms(串行需~1250ms)
======================================
? 性能提升约 3 倍! 这恰恰就是 CompletableFuture 在实际项目中的核心价值所在。
| 特性 | Future(JDK 5) | CompletableFuture(JDK 8) |
|---|---|---|
| 手动完成 | ❌ 不支持 | ✅ complete() |
| 链式调用 | ❌ 不支持 | ✅ thenApply/thenAccept... |
| 多任务组合 | ❌ 不支持 | ✅ allOf/anyOf/thenCombine |
| 异常处理 | ❌ 只能 get() 时捕获 | ✅ exceptionally/handle |
| 非阻塞获取 | ❌ get() 阻塞 | ✅ thenAccept 回调 |
| 超时控制 | ✅ get(timeout) | ✅ orTimeout(JDK9+) |
join() 取代 get(),省去检查异常的烦恼orTimeout 或 completeOnTimeout)allOf 批量等待多个任务,别一个一个去 join| 要点 | 内容 |
|---|---|
| 核心价值 | 非阻塞异步编程,告别 callback hell |
| 创建方式 | supplyAsync(有返回值) / runAsync(无返回值) |
| 链式调用 | thenApply(转换) → thenAccept(消费) → thenRun(收尾) |
| 组合编排 | thenCombine(双任务) / allOf(全完成) / anyOf(任一完成) |
| 异常处理 | exceptionally(恢复) / handle(统一) / whenComplete(日志) |
| 生产要点 | 自定义线程池 + 超时控制 + 早期异常处理 |
? 延伸阅读:
ja va.util.concurrent.CompletableFuture本文基于 JDK 8+ 编写,部分 API(比如 orTimeout)需要 JDK 9+。如果有任何疑问,欢迎交流讨论!
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8