Future & Promise
Future & Promise
核心关系总览
首先,最重要的是理解 Future 和 Promise 的关系。它们其实是同一个异步计算结果的 两个视角:
- Future (只读视角): 对于结果的消费者来说,它是一个 只读 的引用。你可以查看结果是否就绪、等待结果或读取结果,但你不能改变它。
- Promise (可写视角): 对于结果的生产者来说,它是一个 可写 的终端。你有权设置成功的结果或失败的异常,从而完成这个 Future。
可以把它们理解为一个 单次写入的容器:
Promise是 写入端Future是 读取端
核心思想:Future/Promise 就是一个跨线程共享的结果容器
本质:就是一个线程安全的全局变量,一个线程往里写结果,另一个线程从里面读结果
jdk里面的Future & Promise
JDK 的命名和抽象与上述模型不完全一致,这常常是困惑的来源。
| 概念 | JDK 实现 | 说明 |
|---|---|---|
| 只读的 Future | java.util.concurrent.Future |
经典的、阻塞的 Future。只有检查(isDone())和阻塞获取(get())的方法,没有写入或回调的能力。 |
| 可写的 Promise | java.util.concurrent.CompletableFuture |
它同时扮演了 Future 和 Promise 两个角色! 它既是只读的Future,又提供了complete(value), completeExceptionally(cause)等写入方法。 |
JDK 模型图解:
JDK 示例:
// CompletableFuture 同时充当了 Future 和 Promise
CompletableFuture<String> futurePromise = new CompletableFuture<>();
// 生产者线程:扮演 Promise 的角色,负责完成计算
executor.submit(() -> {
try {
String result = doHeavyWork();
futurePromise.complete(result); // 写入成功结果
} catch (Exception e) {
futurePromise.completeExceptionally(e); // 写入异常
}
});
// 消费者线程:扮演 Future 的角色,获取结果
futurePromise.whenComplete((result, exception) -> {
if (exception != null) {
System.out.println("Failed: " + exception.getMessage());
} else {
System.out.println("Success: " + result);
}
});
JDK 标准库中的 Future 实现:
// Future 接口的主要实现类关系
java.util.concurrent.Future<V>
├── java.util.concurrent.RunnableFuture<V>
│ ├── java.util.concurrent.FutureTask<V> // 最常用的实现
│ └── java.util.concurrent.ForkJoinTask<V> // ForkJoin框架专用
│ ├── java.util.concurrent.RecursiveTask<V> // 有返回值的任务
│ └── java.util.concurrent.RecursiveAction // 无返回值的任务
└── java.util.concurrent.CompletableFuture<V> // JDK8+ 最强大的实现
#FutureTask:
#- CAS state 字段
#- int state(volatile) + Object outcome(非volatile)
#CompletableFuture:
#- 直接 CAS result 字段
#- volatile Object result
netty里面的Future & Promise
Netty 的抽象更加纯粹和直接,严格区分了 Future 和 Promise 的接口。
| 概念 | Netty 实现 | 说明 |
|---|---|---|
| 只读的 Future | io.netty.util.concurrent.Future |
扩展了 JDK 的 Future。增加了监听器(Listener)机制,允许异步回调,解决了 JDK 原版 Future 只能阻塞等待的问题。 |
| 可写的 Promise | io.netty.util.concurrent.Promise |
扩展了 Netty 的 Future。增加了 setSuccess(result), setFailure(cause) 等写入方法。 |
Netty 模型图解:

Netty 示例:
// 在 Netty 的 EventLoop 中创建 Promise
EventLoop eventLoop = channel.eventLoop();
Promise<String> promise = eventLoop.newPromise(); // 创建可写端
// 生产者:扮演 Promise 的角色,负责完成计算
eventLoop.execute(() -> {
try {
String result = doHeavyWork();
// 尝试设置结果,注意有 trySuccess 和 setSuccess 的区别
boolean success = promise.trySuccess(result);
} catch (Exception e) {
promise.setFailure(e);
}
});
// 消费者:通过 Future(Promise 的父接口)来读取结果
promise.addListener((Future<String> future) -> { // 这里监听器接收的是 Future
if (future.isSuccess()) {
System.out.println("Success: " + future.get());
} else {
System.out.println("Failed: " + future.cause().getMessage());
}
});
Netty 的 Future/Promise:
// Netty 的 Future 体系
io.netty.util.concurrent.Future<V> // 扩展了JDK Future
├── io.netty.util.concurrent.Promise<V> // 可写的Future
│ └── io.netty.util.concurrent.DefaultPromise<V>
└── io.netty.channel.ChannelFuture // 专门用于Channel操作
└── io.netty.channel.DefaultChannelFuture
对比总结
| 特性 | JDK | Netty |
|---|---|---|
| 抽象清晰度 | 模糊。CompletableFuture 一身二职。 |
清晰。严格区分 Future(读)和 Promise(写)。 |
| 回调机制 | 函数式回调(thenApply, whenComplete)。 |
监听器(Listener)模式。 |
| 核心接口 | Future, CompletableFuture |
Future (扩展JDK), Promise (扩展Netty Future) |
| 设计背景 | 通用并发工具,JDK 8 后引入。 | 为高性能网络I/O定制,在 JDK 8 之前就已存在并成熟。 |
| 与线程模型结合 | 与 ExecutorService 结合。 |
深度集成到 Netty 的 EventLoop 和 Channel 中。 |
如何选择?
- 通用 Java 项目,JDK 8+:直接使用 JDK 的
CompletableFuture,其函数式编程风格非常强大和优雅。 - Netty 网络编程:使用 Netty 的
Future/Promise,因为它们与 Netty 的整个异步IO模型深度绑定,是 Netty 架构的基石。
扩展
首先要说明 netty 中的 Future 与 jdk 中的 Future 同名,但是是两个接口,netty 的 Future 继承自 jdk 的 Future,而 Promise 又对 netty Future 进行了扩展
- jdk Future 只能同步等待任务结束(或成功、或失败)才能得到结果
- netty Future 可以同步等待任务结束得到结果,也可以异步方式得到结果,但都是要等任务结束
- netty Promise 不仅有 netty Future 的功能,而且脱离了任务独立存在,只作为两个线程间传递结果的容器
浙公网安备 33010602011771号