Netty 之 DefaultPromise 源碼解析

概述

promise 是可寫的 future, 因爲 future 不支持寫操作接口,netty 使用 promise 擴展了 future, 可以對異步操作結果進行設置。

DefaultPromise 繼承關係

Promise 接口定義


從接口定義可以看出,Promise 在 Future 接口的基礎上擴展了,可寫的接口。比如 setSuccess()、setFailure() 接口。還支持添加 listener,當執行完成 Promise 後自動回調添加的 listener,這樣就不用再通過 get 阻塞的方式進行處理,提高執行效率。

DefaultPromise 成員變量

public class DefaultPromise<V> extends AbstractFuture<V> implements Promise<V> {
    // 使用 CAS 進行更新執行結果 result 字段。
    private static final AtomicReferenceFieldUpdater<DefaultPromise, Object> RESULT_UPDATER =
            AtomicReferenceFieldUpdater.newUpdater(DefaultPromise.class, Object.class, "result");
    // result 的幾種 value
    private static final Object SUCCESS = new Object();
    private static final Object UNCANCELLABLE = new Object();
    private static final CauseHolder CANCELLATION_CAUSE_HOLDER = new CauseHolder(ThrowableUtil.unknownStackTrace(
            new CancellationException(), DefaultPromise.class, "cancel(...)"));

    // 存儲執行結果的變量
    private volatile Object result;
    // 執行的線程池
    private final EventExecutor executor;

DefaultPromise 是通過 CAS 來進行更新執行的結果 result 字段的。
如果執行完成,無返回值則 result = SUCCESS。 有返回值則 result = 執行結果。
如果執行未完成,result = UNCANCELLABLE。
如果執行異常,result = CANCELLATION_CAUSE_HOLDER。

設置執行成功結果

@Override
public Promise<V> setSuccess(V result) {
    if (setSuccess0(result)) {
        notifyListeners();
        return this;
    }
    throw new IllegalStateException("complete already: " + this);
}

1、調用 setSuccess0() 方法設置執行結果
2、如果設置成功則執行 所有通過addListener(GenericFutureListener<? extends Future<? super V>> listener)方法添加的 listener,並返回當前的 Promise。
3、執行失敗拋出 IllegalStateException 異常

private boolean setSuccess0(V result) {
    return setValue0(result == null ? SUCCESS : result);
}

private boolean setValue0(Object objResult) {
    if (RESULT_UPDATER.compareAndSet(this, null, objResult) ||
        RESULT_UPDATER.compareAndSet(this, UNCANCELLABLE, objResult)) {
        checkNotifyWaiters();
        return true;
    }
    return false;
}

private synchronized void checkNotifyWaiters() {
    if (waiters > 0) {
        notifyAll();
    }
}

1、如果 result == null 則設置爲 SUCCESS,然後調用 setValue0() 方法
2、通過 CAS 設置 DefaultPromise.result 值, 判斷result 是否爲 null 或者 UNCANCELLABLE,如果是則進行修改。如果不是說明已經執行完成(可能成功或失敗)。然後調用checkNotifyWaiters() 方法進行喚醒所有 調用 DefaultPromise.get() 獲取結果的線程。

3、根據 waiters 進行判斷是否有需要喚醒的線程。每一次調用 get() 獲取Promise執行結果的時候都會調用 incWaiters() 方法 ++waiters,執行完後調用 decWaiters() 進行 --waiters。

private void notifyListeners() {
    EventExecutor executor = executor();
    if (executor.inEventLoop()) {
        final InternalThreadLocalMap threadLocals = InternalThreadLocalMap.get();
        final int stackDepth = threadLocals.futureListenerStackDepth();
        if (stackDepth < MAX_LISTENER_STACK_DEPTH) {
            threadLocals.setFutureListenerStackDepth(stackDepth + 1);
            try {
                notifyListenersNow();
            } finally {
                threadLocals.setFutureListenerStackDepth(stackDepth);
            }
            return;
        }
    }

    safeExecute(executor, new Runnable() {
        @Override
        public void run() {
            notifyListenersNow();
        }
    });
}

獲取 EventExecutor ,其實就是 EventLoop,判斷執行 EventExecutor 的線程是否和當前線程一致,如果一致則調用 notifyListenersNow() 方法執行 listener。不一致則將任務封裝成 Runnable 提交到任務隊列中等待執行。

private void notifyListenersNow() {
    Object listeners;
    synchronized (this) {
        // Only proceed if there are listeners to notify and we are not already notifying listeners.
        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) {
            if (this.listeners == null) {
                // Nothing can throw from within this method, so setting notifyingListeners back to false does not
                // need to be in a finally block.
                notifyingListeners = false;
                return;
            }
            listeners = this.listeners;
            this.listeners = null;
        }
    }
}

1、獲取 listeners 值 並將 this.listeners 置爲 null
listeners = this.listeners;
this.listeners = null;
2、調用 notifyListeners0() 或 notifyListener0() 方法執行 listeners
3、執行完 listeners 後,再次判斷 this.listeners 是否爲null,如果不爲null,說明在執行過程中又有新的 listeners 添加進來,繼續 for 循環執行。如果爲 null 則return 退出 死循環。

private void notifyListeners0(DefaultFutureListeners listeners) {
    GenericFutureListener<?>[] a = listeners.listeners();
    int size = listeners.size();
    for (int i = 0; i < size; i ++) {
        notifyListener0(this, a[i]);
    }
}

@SuppressWarnings({ "unchecked", "rawtypes" })
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);
        }
    }
}

執行添加的 listeners。

獲取執行結果

@Override
public V get() throws InterruptedException, ExecutionException {
    await();

    Throwable cause = cause();
    if (cause == null) {
        return getNow();
    }
    if (cause instanceof CancellationException) {
        throw (CancellationException) cause;
    }
    throw new ExecutionException(cause);
}

1、首先判斷該 Promise 是否執行完成,如果執行完成則繼續執行,如果沒有執行完成則掛起當前線程。
2、判斷執行是否有異常,如果沒有異常則直接調用 getNow() 方法獲取返回值。
3、如果有異常則首先判斷異常是否是 CancellationException異常,如果是則直接拋出,不是則使用 ExecutionException 異常包裝再拋出。

@Override
public Promise<V> await() throws InterruptedException {
    if (isDone()) {
        return this;
    }

    if (Thread.interrupted()) {
        throw new InterruptedException(toString());
    }

    checkDeadLock();

    synchronized (this) {
        while (!isDone()) {
            incWaiters();
            try {
                wait();
            } finally {
                decWaiters();
            }
        }
    }
    return this;
}

1、通過 isDone() 方法判斷是否執行完成,如果執行完成直接返回
2、判斷當前線程是否被中斷,如果中斷則直接拋出 InterruptedException 異常
3、檢查執行 Promise 任務的線程是否是當前線程,如果是當前線程再調用 await() 就會發生死鎖的情況,拋出 BlockingOperationException 異常。就相當於獲取結果和執行都是當前線程,自己調用 await() 方法把自己阻塞掉了。

@SuppressWarnings("unchecked")
@Override
public V getNow() {
    Object result = this.result;
    if (result instanceof CauseHolder || result == SUCCESS || result == UNCANCELLABLE) {
        return null;
    }
    return (V) result;
}

如果 Promise 執行無返回結果,當執行完成時會把 result 設置爲 SUCCESS,這裏判斷如果有異常、SUCCESS 和 UNCANCELLABLE 則返回 null,否則返回執行結果 result。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章