一、Promise介绍
JDK的Future接口大家都比较熟悉,它用于表示异步操作的结果
。Netty的Future接口继承于JDK原生的Future接口,并在其之上拓展了一些方法,比如注册监听器addListener
、移除监听器removeListener
、等待异步操作完成await
等方法。相关类图如下:
从上图可以看到,Promise接口继承于Netty的Future接口,也在其之上拓展了一些方法,比如设置结果setSuccess、setFailure,设置不可取消setUncancellable等方法。源码如下:
public interface Promise<V> extends Future<V> {
// 设置结果为成功
Promise<V> setSuccess(V result);
// 尝试设置结果为成功
boolean trySuccess(V result);
// 设置结果为失败
Promise<V> setFailure(Throwable cause);
// 尝试设置结果为失败
boolean tryFailure(Throwable cause);
// 尝试为不可取消
boolean setUncancellable();
// 添加监听器
Promise<V> addListener(GenericFutureListener<? extends Future<? super V>> listener);
Promise<V> addListeners(GenericFutureListener<? extends Future<? super V>>... listeners);
// 移除监听器
Promise<V> removeListener(GenericFutureListener<? extends Future<? super V>> listener);
Promise<V> removeListeners(GenericFutureListener<? extends Future<? super V>>... listeners);
// 可中断地等待
Promise<V> await() throws InterruptedException;
// 不可中断地等待
Promise<V> awaitUninterruptibly();
// 可中断地等待,如果结果为失败,重新抛出异常
Promise<V> sync() throws InterruptedException;
// 不可中断地等待,如果结果为失败,重新抛出异常
Promise<V> syncUninterruptibly();
}
二、DefaultPromise的实现分析
DefaultPromise是Promise的默认实现
,并且后面经常遇到的DefaultChannelPromise
也是继承于它,所以接下来让我们看下DefaultPromise的具体代码实现
2.1 关键属性
DefaultPromise的几个关键属性,如下:
private static final Object SUCCESS = new Object();
private static final Object UNCANCELLABLE = new Object();
private volatile Object result;
private final EventExecutor executor;
private Object listeners;
private short waiters;
private boolean notifyingListeners;
private static final int MAX_LISTENER_STACK_DEPTH = Math.min(8, SystemPropertyUtil.getInt("io.netty.defaultPromise.maxListenerStackDepth", 8));
- SUCCESS:空对象,表示结果为
成功
- UNCANCELABLE:空对象,表示为
不可取消
result:代表结果,它的取值有5种情况(Promise可归为3种状态:
未完成、成功、失败
)- null(状态为
未完成
) - 空对象UNCANCELLABLE(状态为
未完成
) - 空对象SUCCESS(状态为
成功
) - CauseHolder对象,包含了异常信息(状态为
失败
) - 正常执行结果(状态为
成功
)
- null(状态为
- executor:执行器,用于回调监听器
- listeners:
监听器集合
- waiters:等待当前Promise完成的
线程个数
- notifyingListners:是否正在回调监听器
- MAX_LISTENER_STACK_DEPTH:字面翻译为监听器最大栈深度,这是当
嵌套回调
监听器时,防止栈溢出StackOverflowError而设计的,类似如下情况
public class TestPromise {
public static void main(String[] args) {
EventExecutor executor = ImmediateEventExecutor.INSTANCE;
Promise<String> p1 = new DefaultPromise<>(executor);
Promise<String> p2 = new DefaultPromise<>(executor);
Promise<String> p3 = new DefaultPromise<>(executor);
Promise<String> p4 = new DefaultPromise<>(executor);
Promise<String> p5 = new DefaultPromise<>(executor);
Promise<String> p6 = new DefaultPromise<>(executor);
Promise<String> p7 = new DefaultPromise<>(executor);
Promise<String> p8 = new DefaultPromise<>(executor);
Promise<String> p9 = new DefaultPromise<>(executor);
Promise<String> p10 = new DefaultPromise<>(executor);
p1.addListener(new MyListener(p2));
p2.addListener(new MyListener(p3));
p3.addListener(new MyListener(p4));
p4.addListener(new MyListener(p5));
p5.addListener(new MyListener(p6));
p6.addListener(new MyListener(p7));
p7.addListener(new MyListener(p8));
p8.addListener(new MyListener(p9));
p9.addListener(new MyListener(p10));
p1.setSuccess(null);
}
private static class MyListener implements GenericFutureListener {
private Promise promise;
MyListener(Promise promise) {
this.promise = promise;
}
@Override
public void operationComplete(Future future) throws Exception {
System.out.println("回调成功");
promise.setSuccess(null);
}
}
}
2.2 设置结果
2.2.1 设置结果为成功或失败
通过setSuccess、setFailure
方法来设置Promise的最终结果result,源码如下
// 设置Promise的最终结果为参数result,如果设置失败,则抛出异常
public Promise<V> setSuccess(V result) {
if (setSuccess0(result)) {
return this;
}
throw new IllegalStateException("complete already: " + this);
}
// 设置Promise的最终结果为new CauseHolder(cause),如果设置失败,则抛出异常
public Promise<V> setFailure(Throwable cause) {
if (setFailure0(cause)) {
return this;
}
throw new IllegalStateException("complete already: " + this, cause);
}
private boolean setSuccess0(V result) {
// 如果传入的result为null,则设置最终结果为SUCCESS
return setValue0(result == null ? SUCCESS : result);
}
private boolean setFailure0(Throwable cause) {
// 将传入的cause封装为CauseHolder对象,并设置为最终结果
return setValue0(new CauseHolder(checkNotNull(cause, "cause")));
}
private boolean setValue0(Object objResult) {
/**
* 最终结果result为null,表示当前Promise处于未完成状态
* 最终结果result为UNCANCELLABLE,表示当前Promise不可取消,也是处于未完成状态
* 通过CAS操作来更新最终结果,如果更新成功,唤醒等待当前Promise的线程,并且回调监听器
* 如果更新失败,直接返回false
*/
if (RESULT_UPDATER.compareAndSet(this, null, objResult) ||
RESULT_UPDATER.compareAndSet(this, UNCANCELLABLE, objResult)) {
// 唤醒等待当前Promise的线程
if (checkNotifyWaiters()) {
// 回调监听器
notifyListeners();
}
return true;
}
return false;
}
2.2.2 设置为UNCANCELLABLE(不可取消)
当Promise未完成时,通过setUncancellable()方法将最终结果result暂时更新
为UNCANCELLABLE,后续调用cancel()将都会返回false,当Promise完成后,会再将最终结果result更新为完成结果。
public boolean setUncancellable() {
// CAS操作将最终结果result暂时更新为UNCANCELLABLE
if (RESULT_UPDATER.compareAndSet(this, null, UNCANCELLABLE)) {
return true;
}
Object result = this.result;
return !isDone0(result) || !isCancelled0(result);
}
2.3 利用wait/notify机制来实现等待唤醒
2.3.1 等待完成await
await方法可以使当前线程等待Promise完成,其大致流程为:
- 判断Promise是否
已完成
,如果是,直接返回,否则下一步 - 判断当前线程是否
已被中断
,如果是,直接抛出异常,否则下一步 - 检查当前线程对应的执行器是否是EventLoop,如果是,直接抛出异常,否则下一步
- synchronized加锁,再次判断Promise是否已完成
如果是,直接返回
如果不是,waiters加1,并调用wait()方法进入等待唤醒状态
,当被唤醒时,waiters减1
源码如下:
public Promise<V> await() throws InterruptedException {
// 判断是否已完成,如果是,直接返回
if (isDone()) {
return this;
}
// 判断当前线程是否已被中断,如果是,直接抛出异常
if (Thread.interrupted()) {
throw new InterruptedException(toString());
}
// 检测当前线程对应的执行器是否是EventLoop,如果是,则判定为死锁,直接抛出异常
checkDeadLock();
synchronized (this) {
while (!isDone()) {
incWaiters(); // waiters加1
try {
wait(); // 释放锁,并等待唤醒
} finally {
decWaiters(); // waiters减1
}
}
}
return this;
}
2.3.2 唤醒等待的线程
通过checkNotifyWaiters来唤醒等待的线程,如下:
private synchronized boolean checkNotifyWaiters() {
if (waiters > 0) { // 如果waiters大于0,表示有等待的线程,唤醒所有等待线程
notifyAll();
}
return listeners != null;
}
那么何时唤醒
等待的线程呢?
- 当成功设置最终结果之后,会唤醒等待的线程
- 当调用cancel方法来成功取消Promise时,会唤醒等待的线程
2.4 注册、移除监听器以及回调监听器
2.4.1 注册、移除监听器
- 通过addListener来注册监听器,如果Promise已完成,直接回调监听器
- 通过removeListener来移除监听器
// 注册监听器
public Promise<V> addListener(GenericFutureListener<? extends Future<? super V>> listener) {
checkNotNull(listener, "listener");
// 加锁
synchronized (this) {
addListener0(listener); // 注册监听器
}
// 判断是否已完成,如果已完成,直接回调监听器
if (isDone()) {
notifyListeners();
}
return this;
}
private void addListener0(GenericFutureListener<? extends Future<? super V>> listener) {
if (listeners == null) { // 首次注册监听器
listeners = listener;
} else if (listeners instanceof DefaultFutureListeners) { // 第三次及以后注册监听器
((DefaultFutureListeners) listeners).add(listener);
} else { // 第二次注册监听器
listeners = new DefaultFutureListeners((GenericFutureListener<?>) listeners, listener);
}
}
// 移除监听器
public Promise<V> removeListener(final GenericFutureListener<? extends Future<? super V>> listener) {
checkNotNull(listener, "listener");
// 加锁
synchronized (this) {
removeListener0(listener); // 移除监听器
}
return this;
}
private void removeListener0(GenericFutureListener<? extends Future<? super V>> listener) {
if (listeners instanceof DefaultFutureListeners) {
// 移除对应的监听器
((DefaultFutureListeners) listeners).remove(listener);
} else if (listeners == listener) { // 原本只注册了一个监听器
listeners = null;
}
}
2.4.2 回调监听器
当Promise完成时,会回调已经注册过的监听器,回调监听器的源码如下:
// 回调监听器
private void notifyListeners() {
EventExecutor executor = executor();
// 判断当前线程是否EventLoop绑定的线程是同一个
if (executor.inEventLoop()) {
final InternalThreadLocalMap threadLocals = InternalThreadLocalMap.get();
final int stackDepth = threadLocals.futureListenerStackDepth();
// 判断是否小于MAX_LISTENER_STACK_DEPTH
if (stackDepth < MAX_LISTENER_STACK_DEPTH) {
threadLocals.setFutureListenerStackDepth(stackDepth + 1);
try {
// 回调监听器
notifyListenersNow();
} finally {
threadLocals.setFutureListenerStackDepth(stackDepth);
}
return;
}
}
// 安全执行,防止当前线程抛出StackOverflowError导致
safeExecute(executor, new Runnable() {
@Override
public void run() {
notifyListenersNow();
}
});
}
private void notifyListenersNow() {
Object listeners;
// 加锁
synchronized (this) {
// 如果当前Promise正在回调监听器,或者没有注册监听器,直接返回
if (notifyingListeners || this.listeners == null) {
return;
}
notifyingListeners = true; // 表示正在回调监听器
listeners = this.listeners;
this.listeners = null;
}
for (;;) {
if (listeners instanceof DefaultFutureListeners) {
// 遍历监听器,并逐一回调
notifyListeners0((DefaultFutureListeners) listeners);
} else {
// 回调单个监听器
notifyListener0(this, (GenericFutureListener<?>) listeners);
}
synchronized (this) {
// 当this.listeners等于null,表示当前Promise已经没有可回调的监听器了
if (this.listeners == null) {
notifyingListeners = false;
return;
}
listeners = this.listeners;
this.listeners = null;
}
}
}
// 回调单个监听器
private static void notifyListener0(Future future, GenericFutureListener l) {
try {
l.operationComplete(future);
} catch (Throwable t) {
if (logger.isWarnEnabled()) {
logger.warn("An exception was thrown by " + l.getClass().getName() + ".operationComplete()", t);
}
}
}
三、总结
Netty中所有的异步操作
都是通过Promise来实现的,所以理解Promise对于我们后续深入理解Netty是很有必要的。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。