本文主要是介绍Java中的CompletableFuture核心用法和常见场景,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
《Java中的CompletableFuture核心用法和常见场景》CompletableFuture是Java8引入的强大的异步编程工具,支持链式异步编程、组合、异常处理和回调,介绍其核心用法,通过...
1、引言
CompletableFuture 是 Java 8 引入的一个非常强大的异步编程工具,属于 java.util.concurrent 包。它不仅支持异步执行任务,还支持任务的组合、异常处理、回调等丰富的操作。下面我会详细介绍 CompletableFuture 的核心用法和常见场景。
2. 基本概念
- Future:早期的异步结果表示,功能有限,只能通过
get()阻塞获取结果。 - CompletableFuture:增强版的 Future,支持链式异步编程、组合、异常处理、回调等。
3. 创建 CompletableFuture
3.1. 手动创建
CompletableFuture<String> future = new CompletableFuture<>();
// 可以手动完成
future.complete("Hello");3.2. 通过静态工厂方法
supplyAsync:有返回值,异步执行runAsync:无返回值,异步执行
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
// 模拟耗时操作
return "Hello CompletableFuture";
});
CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> {
// 执行某些操作
});4. 获取结果
get():阻塞等待结果join():类似于get(),但遇到异常会抛出 unchecked 异常
String result = future1.get(); // 可能抛出异常 Strinhttp://www.chinasem.cng result2 = future1.join(); // RuntimeException
5. 回调和链式操作
5.1. thenApply / thenApplyAsync
对结果进行转换(有返回值)
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 100)
.thenApply(i -> i + 10); // 结果为1105.2. thenAccept / thenAcceptAsync
对结果做处理,无返回值
CompletableFuture.supplyAsync(() -> "hello")
.thenAccept(s -> System.out.println(s));5.3. thenRun / thenRunAsync
无参数、无返回值,仅执行后续操作
CompletableFuture.supplyAsync(() -> "hello")
.thenRun(() -> System.out.println("任务执行完毕"));6. 任务组合
5.1. thenCombine / thenCombineAsync
两个任务都完成后,合并结果
CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(() -> 10); CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(() -> 20); CompletableFuture<Integer> result = f1.thenCombine(f2, (a, b) -> a + b); //ouqpHfkHf 30
6.2. thenCompose / thenComposeAsync
任务依赖,前一个结果作为后一个输入
CompletableFuture<String> f = CompletableFuture.supplyAsync(() -> "Hello")
.thenCompose(s -> CompletableFuture.supplyAsync(() -> s + " World"));6.3. allOf / anyOf
等待多个任务全部/任一完成
CompletableFuture<Void> all = CompletableFuture.allOf(f1, f2); all.join(); // 等待全部完成 CompletableFuture<Object> any = CompletableFuture.anyOf(f1, f2); Object fastest = any.join(); // 任意一个完成即可
7. 异常处理
7.1. exceptionally
捕获异常,返回默认值
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
throw new RuntimeException("出错了");
}).exceptionally(e -> {
System.out.println(e.getMessage());
return 0;
});7.2. handle / handleAsync
无论成功或失败都处理
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
throw new RuntimeException("出错了");
}).handle((result, ex) -> {
if (ex != null) {
System.out.println(ex.getMessage());
return 0;
}
return result;
});8. 自定义线程池
默认使用 ForkJoinPool.commonPool(),可以自定义线程池:
ExecutorService executor = Executors.newFixedThreadPool(2); CompletableFuture.supplyAsync(() -> "hello", executor);
9. 实用示例
9.1. 多个异步任务并发执行,最后汇总
CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> "A");
CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> "B");
CompletableFuture<String> f3 = CompletableFuture.supplyAsync(() -> "C");
CompletableFuture<Void> all = CompletableFuture.allOf(f1, f2, f3);
all.thenRun(() -> {
try {
System.out.println(f1.get() + f2.get() + f3.get());
} catch (Exception e) {
e.printStackTrace();
}
});10. 注意事项
- 尽量避免阻塞(如
get()),推荐使用回调。 - 注意线程池资源,合理分配,避免 OOM。
- 处理好异常,避免线程池线程被异常吞掉。
11. 进阶用法
11.1. 串联和并联任务
串联(依赖关系)
当一个任务的结果依赖于另一个任务时,使用 thenCompose:
CompletableFuture<String> getUserId = CompletableFuture.supplyAsync(() -> "user123");
CompletableFuture<String> getUserInfo = getUserId.thenCompose(id ->
CompletableFuture.supplyAsync(() -> "用户信息:" + id)
);并联(聚合结果)
多个任务并发执行,最后聚合结果:
CompletableFuture<Integer> t1 = CompletableFuture.supplyAsynChina编程c(() -> 1http://www.chinasem.cn); CompletableFuture<Integer> t2 = CompletableFuture.supplyAsync(() -> 2); CompletableFuture<Integer> t3 = CompletableFuture.supplyAsync(() -> 3); CompletableFuture<List<Integer>> all = CompletableFuture.allOf(t1, t2, t3) .thenApply(v -> { List<Integer> result = new ArrayList<>(); result.add(t1.join()); result.add(t2.join()); result.add(t3.join()); return result; });
11.2. 超时控制
Java 9 后,CompletableFuture 增加了超时相关方法:
future.orTimeout(3, TimeUnit.SECONDS)
.exceptionally(ex -> {
System.out.println("超时啦");
return null;
});或自己实现:
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
Thread.sleep(5000);
return "hello";
});
try {
String result = future.get(2, TimeUnit.SECONDS); // 2秒超时
} catch (TimeoutException e) {
System.out.println("超时了");
}11.3. 异步流水线
你可以链式地组合多个异步操作,形成“流水线”:
CompletableFuture.supplyAsync(() -> "A")
.thenApply(s -> s + "B")
.thenApply(s -> s + "C")
.thenAccept(System.out::println); // 输出 ABC11.4. 处理异常和兜底方案
推荐使用 handle 或 exceptionally 做兜底:
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
throw new RuntimeException("出错了");
})
.handle((result, ex) -> ex == null ? result : -1);11.5. 自定义线程池的好处
- 控制线程数量,避免公共线程池被占满。
- 适合高并发、IO密集型场景。
ExecutorService executor = Executors.newFixedThreadPool(10); CompletableFuture.supplyAsync(() -> "业务逻辑", executor);
12. 实战场景举例
12.1. 微服务并发调用
假设要并发调用三个微服务接口,最后聚合结果:
CompletableFuture<String> api1 = CompletableFuture.supplyAsync(() -> callApi1());
CompletableFuture<String> api2 = CompletableFuture.supplyAsync(() -> callApi2());
CompletableFuture<String> api3 = CompletableFuture.supplyAsync(() -> callApi3());
CompletableFuture<Void> all = CompletableFuture.allOf(api1, api2, api3);
all.thenAccept(v -> {
String r1 = api1.join();
String r2 = api2.join();
String r3 = api3.join();
System.out.println("聚合结果:" + r1 + r2 + r3);
});12.2. 异ouqpHfkHf步写数据库+异步发消息
CompletableFuture<Void> saveDb = CompletableFuture.runAsync(() -> saveToDb());
CompletableFuture<Void> sendMsg = CompletableFuture.runAsync(() -> sendMsg());
CompletableFuture.allOf(saveDb, sendMsg)
.thenRun(() -> System.out.println("所有操作完成"));13. 常见问题与建议
- 线程池泄漏:线程池要合理关闭,避免资源泄漏。
- 异常未处理:建议所有链路最后加
.exceptionally或.handle。 - 阻塞等待:尽量用回调而不是
get()或join()。 - 链式操作:推荐链式编程,代码更清晰。
总结
CompletableFuture 是 Java 异步编程的利器,支持丰富的组合、回调和异常处理能力。合理使用可以极大提升程序的并发能力和响应速度。
到此这篇关于Java中的CompletableFuture核心用法和常见场景的文章就介绍到这了,更多相关java completablefuture使用内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持China编程(www.chinasem.cn)!
这篇关于Java中的CompletableFuture核心用法和常见场景的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!