CompletableFuture实现线程池管理的方法与实践
时间:2026-08-15 | 作者:怪兽小助手 | 阅读:0Callable接口做多线程开发时,通常会借助FutureTask来管理并拿到线程执行结果。
但问题也恰恰出在这里:它在获取结果时,基本还是依赖阻塞或轮询这两种方式。这不仅有点背离多线程编程追求的高效初衷,还会额外消耗不少资源。
也正因为如此,JDK 8专门针对FutureTask这类短板做了增强,推出了一个非常实用的函数式异步编程辅助类CompletableFuture。
这个类同时实现了Future接口和CompletionStage接口(Ja va 8中新增的一个线程任务完成结果接口)。它在Future能力之上做了大幅扩展,也让异步编程这件事变得简单了很多。
CompletableFuture对象的创建方式
在使用CompletableFuture类在进行线程管理时,通常会使用四个静态方法来为一段异步执行的代码创建CompletableFuture对象,具体如表1所示。
表1 CompletableFuture对象创建的四个静态方法
| 方法声明 | 功能描述 |
|---|---|
| static CompletableFuture |
以Runnable函数式接口类型为参数,并使用ForkJoinPool.commonPool()作为它的线程池执行异步代码获取CompletableFuture计算结果为空的对象 |
| static CompletableFuture |
以Runnable函数式接口类型为参数,并传入指定的线程池执行器executor来获取CompletableFuture计算结果为空的对象 |
| static CompletableFuture supplyAsync(Supplier supplier) | 以Supplier函数式接口类型为参数,并使用ForkJoinPool.commonPool()作为它的线程池执行异步代码获取CompletableFuture计算结果非空的对象 |
| static CompletableFuture supplyAsync(Supplier supplier, Executor executor) | 以Supplier函数式接口类型为参数,并传入指定的线程池执行器executor来获取CompletableFuture计算结果非空的对象 |
两个核心区别
- runAsync()和supplyAsync()的本质区别,在于获取的CompletableFuture对象是否带有计算结果。这个区别类似于Runnable接口和Callable接口的区别。
- 带有Executor参数的方法,用于传入指定的线程池执行器来进行多线程管理;未带有Executor参数的方法,会使用默认的ForkJoinPool.commonPool()作为它的线程池进行多线程管理。
案例:通过CompletableFuture实现线程池管理
了解了创建CompletableFuture对象的常用方法后,接下来通过一个案例来演示如何通过CompletableFuture来实现线程池管理,如文件1所示。
文件1 Example19.ja va
1 import ja va.util.concurrent.*;
2 public class Example19 {
3 public static void main(String[] args) throws InterruptedException,
4 ExecutionException {
5 // 1、创建第一个线程,执行1到5相加运算
6 CompletableFuture completableFuture1 =
7 CompletableFuture.supplyAsync(() -> {
8 int sum = 0, i = 0;
9 while (i++ < 5) {
10 sum += i;
11 // 显示线程任务执行过程
12 System.out.println(Thread.currentThread().getName()
13 + "线程任务正在执行...i:" + i);
14 }
15 return sum;
16 });
17 // 创建第二个线程,执行6到10相加运算
18 CompletableFuture completableFuture2 =
19 CompletableFuture.supplyAsync(() -> {
20 int sum = 0, j = 5;
21 while (j++ < 10) {
22 sum += j;
23 System.out.println(Thread.currentThread().getName()
24 + "线程任务正在执行...j:" + j);
25 }
26 return sum;
27 });
28 // 2、将两个线程执行结果进行获取整合
29 CompletableFuture completableFuture3 =
30 completableFuture1.thenCombine(completableFuture2,
31 (result1, result2) -> result1 + result2);
32 System.out.println("1到10相加的结果为:"
33 + completableFuture3.get());
34 }
35 }
运行结果如图1所示。
图1 运行结果
运行结果分析
从图1可以看出,在执行1到10相加运算时,将启动的两个线程worker-1和worker-2默认提交到了ForkJoinPool.commonPool()线程池进行管理。
与此同时,还可以整合获取这两个线程任务的执行结果。
小提示
运行文件1中的这段代码时,确实有可能出现这样一种情况:线程池里只有一个线程,比如worker-1,把1到5和6到10这两段求和任务都包办了。
原因并不复杂,关键就在于这个案例使用的是线程池来统一调度任务。
1到5求和、6到10求和这两个子任务在执行时,线程池中的空闲线程都会去竞争执行机会。于是,就可能出现这样的结果:worker-1刚跑完前一个任务,紧接着又抢到了下一个任务的执行权。
这样一来,1到10的求和过程就可能始终落在同一个线程的执行控制之下。
免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。
相关文章
更多-
- Dart Future 讲清楚:定义、创建方式、组合处理与结果回调
- 时间:2026-08-25
-
- Dart 异步编程:把 Future 的核心用法一次讲清
- 时间:2026-08-24
-
- Java 并发编程之 CompletableFuture 异步编程实战指南
- 时间:2026-08-22
-
- Dart中Future与Stream的区别及使用场景
- 时间:2026-08-21
-
- 深入理解 Dart Future:带并发数限制的请求实现原理
- 时间:2026-08-21
-
- Dart异步编程基础入门:Future与async/await详解
- 时间:2026-08-21
-
- WAIC2026上175个早期项目谁将成为下一个AI巨头
- 时间:2026-07-28
-
- 个早期项目亮相WAIC 2026,谁将成为下一个AI巨头?
- 时间:2026-07-28
精选合集
更多大家都在玩
大家都在看
更多-
- 以下哪种食材被称为“地下苹果” 蚂蚁庄园今日答案9.18
- 时间:2026-09-17
-
- 蚂蚁庄园今天答题答案2026年9月18日
- 时间:2026-09-17
-
- 蚂蚁庄园答题今日答案2026年9月18日
- 时间:2026-09-17
-
- 蚂蚁庄园小课堂2026年9月18日最新题目答案
- 时间:2026-09-17
-
- 小鸡答题今天的答案是什么2026年9月18日
- 时间:2026-09-17
-
- 蚂蚁庄园每日答题答案2026年9月18日
- 时间:2026-09-17
-
- 蔬菜洗完掉色,说明是被染色了,是真的吗 蚂蚁庄园今日答案9月18日
- 时间:2026-09-17
-
- 满襟蜡绘花纹巧染就花纹当绣裳说的是哪种传统技艺 蚂蚁新村今日答案2026.9.17
- 时间:2026-09-17
