-- [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 单独的日志名称,因此能够单独配置。日志