文章目录
前言
看 《Java8 实战》后,觉得自己对多线程应用还是停留在 JUC 工具类的使用上,忽略了 CompletableFuture 这么强大的工具。本文主要内容
- 复习并行、并发的概念。
- 多线程的编程模型
- CompletableFuture 让多线程编程更加清爽
- 有时间的话,补充 CompletableFuture 的内部原理
1. 并发(Concurrent) 和 并行(Parallel)
Concurrent 和 Parallel 作为形容词,并列到一起。对应Java 的类名/方法名 也有所体现:
- ConcurrentHashMap
- parallelStream()

1.1 并发的来源
在单核CPU的时代,根本不可能真正同时运行一个以上的线程(进程是线程的容器,Linux是把时间片分给线程)。
假设有网易音乐、Chrome浏览器这两个应用需要同时运行,操作系统会 轮流 把这两个应用的任务放到同一个线程上执行。
宏观上看,CPU把时间片分给了不同应用,不同应用持有单个线程某一段时间的运行权力。这就是并发技术。
1.2 并发技术解决了什么问题
在 web 技术中,同一时刻请求的接收能力提高了,具体的:
如果有耗时较长的数据库查询、外部资源请求,一个线程不具有并发能力则耗时操作会一直阻塞后面的请求。
2. 并行的来源
多核CPU的出现
2.1 并行解决了什么问题
除了压榨硬件资源从而提高响应速度外,还尽可能减少任务之间的并发度。因为一个CPU核心管一个任务的情况下,任务之间是隔离的,也就是线程安全的。
3. CompletableFuture 简介
这个类是 Java 8 引入的,用于解决 Futrue 异步编程的局限性:
- Futrue 任务之间的依赖关系很难表达
- 等待Futrue集合中的所有任务都完成
- 应对Future的完成事件
“可以说 CompletableFuture 和 Future 的关系就跟 Stream 和 Collections的关系一样”
4. CompletableFuture 简单应用
- 定义一个异步任务
public Future<Double> getPriceAsync(String product) {
// 用于接收异步任务的响应
CompletableFuture<Double> futurePrice = new CompletableFuture<>();
// 异步任务
new Thread( () -> {
try {
double price = calculatePrice(product);
// 异步任务完成后通知(带上返回值)
futurePrice.complete(price);
} catch (Exception ex) {
// 异步任务有异常,也会通知调用方
futurePrice.completeExceptionally(ex);
}
}
).start();
return futurePrice;
}
- 调用异步任务
Future<Double> futurePrice = shop.getPriceAsync("my favorite product"

本文介绍了并发和并行的概念,以及它们在多线程编程中的作用。重点讲解了Java8中的CompletableFuture类,它是为了解决Future异步编程的局限性而引入的。通过示例展示了CompletableFuture的创建、应用、工厂方法、join()方法、任务编排、响应completion事件和异常处理,强调了在计算密集型和IO密集型任务中何时选择使用CompletableFuture或ParallelStream。
最低0.47元/天 解锁文章
1万+

被折叠的 条评论
为什么被折叠?



