Future & Promise

Future & Promise

核心关系总览

首先,最重要的是理解 FuturePromise 的关系。它们其实是同一个异步计算结果的 两个视角

  • Future (只读视角): 对于结果的消费者来说,它是一个 只读 的引用。你可以查看结果是否就绪、等待结果或读取结果,但你不能改变它。
  • Promise (可写视角): 对于结果的生产者来说,它是一个 可写 的终端。你有权设置成功的结果或失败的异常,从而完成这个 Future。

可以把它们理解为一个 单次写入的容器

  • Promise写入端
  • Future读取端
image-20251117111033867

核心思想: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 模型图解:

image-20251117111428148

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 模型图解:

image-20251117112119989

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 的 EventLoopChannel 中。

如何选择?

  • 通用 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 的功能,而且脱离了任务独立存在,只作为两个线程间传递结果的容器

详细查看:Netty02-入门 - Future & Promise - 博客园

posted @ 2025-11-18 09:17  deyang  阅读(16)  评论(0)    收藏  举报