-- [I]java.util.concurrent.Future<V> ---- [I]io.netty.util.concurrent.Future<V> ------ [AC]AbstractFuture, [I]ChannelFuture, [I]Promise -- [AC]AbstractFuture, [I]Promise -- [I]ChannelFuture, [I]Promise ---- DefaultPromise ---- [I]ChannelPromise -- [I]ChannelPromise, [I]FlushCheckpoint, [C]DefaultPromise ---- [C]DefaultChannelPromise
總體定位是一個支持可寫的Future,能夠理解成:能夠經過API設置結果的成功仍是失敗。對應netty的Future的特性1。html
注意: 是否能夠取消,是否成功等,在DefaultPromise實現中,是用一個result字段來實現的。而且用AtomicReferenceFieldUpdater結合volatile來完成在併發狀況下字段的正確設置值。java
完成get的實現邏輯,或者說定義的行爲順序,包含超時的get與一直等的get數組
+-----------+ | await | +-----+-----+ | | +--------v-------+ | get cause | +----+ cause == null +---+ | +----------------+ | | | | | +------v------+ +------v------+ | throw exp | | getNow | +-------------+ +-------------+
實現是線程安全的promise
await邏輯安全
+----------------+ +----Y-----+ isDone | +----v---+ +----------------+ | return | N +------+-+ | ^ +-------v--------+ +----Y---+ interrupted | +----------------+ N | +----------+ +-------v--------+ | throw exp<--Y---+ checkDeadLock | +----------+ +----------------+ N +---------synchronized----------+ | | | | +-------v--------+ | while-loop-+ !isDone +-----------+ | | +----------------+ +-------v------+ | | | incWaiters | | | +-------+------+ | | +----------------+ | | | | wait <-----------+ | | +-------+--------+ | | | +--------------+ | | +------------> decWaiters | | | +--------------+ | +-------------------------------------------+ | | +-------------------------------+
若是有其餘人作了notify 可是此時任務尚未done,那麼則會繼續wait,由於這是一個while loop!併發
觸發監聽器邏輯有棧深度保護策略
前提是在同一個線程上,若是不是同一個線程就沒有意義了。因此要判斷executor.inEventLoop()。
在UnpaddedInternalThreadLocalMap中有個字段int futureListenerStackDepth字段來維護FutureListener的棧深度。
在同一個線程上,作notifyListener0以前會將futureListenerStackDepth加1,作完以後恢復原值。
這樣若是在同一個線程遞歸調用到notifyListener0即notifyListener則會觸發觸發監聽器邏輯有棧深度保護策略。
棧深度保護閾值默認是8,能夠經過io.netty.defaultPromise.maxListenerStackDepth系統參數配置。oop
關於Promise的監聽器
監聽器是用listeners字段,這個字段是Object類型,居然沒有給一個明確的類型。在邏輯實現中有DefaultFutureListeners、GenericProgressiveFutureListener與GenericFutureListener等。
裏面包了一個GenericFutureListener數組,達成一個複合的(列表型的)Listener。
GenericProgressiveFutureListener在netty自身裏面沒有用到具體實現。.net
安全執行任務的包裝線程
private static void safeExecute(EventExecutor executor, Runnable task) { try { executor.execute(task); } catch (Throwable t) { rejectedExecutionLogger.error("Failed to submit a listener notification task. Event loop shut down?", t); } }
注意: rejectedExecutionLogger 單獨的日誌名稱,因此能夠單獨配置。日誌