1. 优势
-
✅ 非阻塞的异步编程
-
✅ 声明式链式调用
-
✅ 强大的组合能力
-
✅ 丰富的异常处理
-
✅ 手动设置结果的能力
2. 入门
1. 先学两个入口
只有这两个最重要:
- runAsync(...)
没有返回值,适合"异步做一件事" - supplyAsync(...)
有返回值,适合"异步算一个结果"
java
CompletableFuture<Void> f1 = CompletableFuture.runAsync(() -> {
System.out.println("异步执行任务");
}, executor);
CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> {
return "查询结果";
}, executor);
2. 结果回来后怎么接
最常用 3 个:
- thenApply
有入参,有返回值。适合"转换结果" - thenAccept
有入参,无返回值。适合"消费结果" - thenRun
没入参,没返回值。适合"只想接着执行"
java
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "abc", executor);
CompletableFuture<Integer> lenFuture = future.thenApply(s -> s.length());
CompletableFuture<Void> saveFuture = future.thenAccept(s -> {
System.out.println("保存结果: " + s);
});
CompletableFuture<Void> logFuture = future.thenRun(() -> {
System.out.println("任务结束");
});
3. 异常怎么处理
最常用 2 个:
- exceptionally
出错时兜底 - handle
不管成功失败都能处理
java
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
if (true) throw new RuntimeException("出错了");
return "ok";
}, executor).exceptionally(ex -> {
System.out.println("捕获异常: " + ex.getMessage());
return "默认值";
});
java
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
if (true) throw new RuntimeException("出错了");
return "ok";
}, executor).exceptionally(ex -> {
System.out.println("捕获异常: " + ex.getMessage());
return "默认值";
});
4. 多个异步任务一起跑
这也是 CompletableFuture 很强的地方。
allOf(...):等全部完成
anyOf(...):谁先完成用谁
java
CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(() -> 1, executor);
CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(() -> 2, executor);
CompletableFuture<Void> all = CompletableFuture.allOf(f1, f2);
all.join(); // 等全部完成
int sum = f1.join() + f2.join();
System.out.println(sum);
5. join() 和 get() 的区别
两者都是"等结果"。
- get()
抛检查异常,写法啰嗦 - join()
抛运行时异常,写法更简洁
一般项目里更常见 join()。
java
String result = future.join();
6. thenApply 和 thenCompose 的区别
这个新手最容易混。
如果你的下一步返回的是"普通值",用 thenApply。
如果你的下一步返回的是"另一个 CompletableFuture",用 thenCompose。
java
CompletableFuture<String> f =
CompletableFuture.supplyAsync(() -> "userId", executor)
.thenCompose(userId -> CompletableFuture.supplyAsync(() -> "order of " + userId, executor));
7. 线程池很重要
如果你不传线程池,默认会走公共线程池 ForkJoinPool.commonPool()。
java
CompletableFuture.supplyAsync(() -> query(), modelApiThreadPool);