接口与类结构体系

-- [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

JDK的Future提供特性

  1. 是否完成
  2. 是否取消
  3. 结果获取
  4. 取消执行

netty的Future增加的特性

  1. 是否成功(完成后的结果,完成不一定成功)
  2. 是否能被取消
  3. 如果失败时的异常获取
  4. 支持监听器,监听操作完成的回调
  5. sync 阻塞等待直至完成 // 跟get有什么区别?A: 只阻塞,不取结果,在一些实现逻辑中而有是否死锁等检查。
  6. await 阻塞等待直至完成 // 跟get有什么区别?跟sync有什么区别?A: 在一些实现逻辑中多了在调完await之后再调用rethrowIfFailed(字面意思)。
  7. getNow,非阻塞获取结果(可以理解成JDK Future的是否完成和结果获取的组合)
  8. 重新覆写cancel行为定义

Promise增加的特性

整体定位是一个支持可写的Future,可以理解成:可以通过API设置结果的成功还是失败。对应netty的Future的特性1。

  1. 设置是否成功的结果,并触发监听器operationComplete事件。操作失败抛异常
  2. 尝试设置是否成功的结果, 并触发监听器operationComplete事件。操作失返回false
  3. 设置是否失败的结果,并触发监听器operationComplete事件。操作失败抛异常
  4. 尝试设置是否失败的结果, 并触发监听器operationComplete事件。操作失返回false
  5. 设置是否可以取消
  6. 覆写返回Future的方法签名为返回Promise

注意: 是否可以取消,是否成功等,在DefaultPromise实现中,是用一个result字段来实现的。并且用AtomicReferenceFieldUpdater结合volatile来完成在并发情况下字段的正确设置值。

ChannelPromise增加的特性
  1. 覆写返回ChannelFuture的方法签名为返回ChannelPromise
  2. unvoid行为(如果是void的则返回新的ChannelPromise,否则返回当前实例)
AbstractFuture完成的逻辑

完成get的实现逻辑,或者说定义的行为顺序,包含超时的get与一直等的get

               +-----------+
| await |
+-----+-----+
|
|
+--------v-------+
| get cause |
+----+ cause == null +---+
| +----------------+ |
| |
| |
+------v------+ +------v------+
| throw exp | | getNow |
+-------------+ +-------------+

DefaultPromise完成的逻辑

实现是线程安全的

  1. 实现监听器添加、删除与触发逻辑。引入EventExecutor实例,一对一。 用于触发监听器时使用。触发监听器逻辑有栈深度保护策略。
  2. 通过volatile Object result字段完成是否成功,是否取消的状态描述。
  3. 实现设置(含尝试)成功,设置失败(含尝试),设置不可取消的逻辑
  4. 实现是否成功,是否取消的判断逻辑
  5. 异常的获取,结果的获取
  6. await逻辑的实现。依靠Object的wait方法实现。同时用short waiters来描述wait的次数。
  7. 获取执行结果。执行结果也是volatile Object result字段承载。
  8. 取消逻辑实现。设置result字段为CANCELLATION_CAUSE_HOLDER。notifyAll wait。notify所有监听器。
  9. 是否取消的判断逻辑实现。比对result字段值,比对cause字段的异常类型
  10. 是否完成的判断逻辑实现。与是否取消逻辑类似。
  11. sync逻辑实现。在调完await之后再调用rethrowIfFailed(字面意思)。
  12. 死锁检测逻辑实现。如果executor在eventLoop则死锁(executor.inEventLoop)。死锁扔异常BlockingOperationException

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系统参数配置。

关于Promise的监听器

监听器是用listeners字段,这个字段是Object类型,竟然没有给一个明确的类型。在逻辑实现中有DefaultFutureListeners、GenericProgressiveFutureListener与GenericFutureListener等。

里面包了一个GenericFutureListener数组,达成一个复合的(列表型的)Listener。

GenericProgressiveFutureListener在netty自身里面没有用到具体实现。

安全执行任务的包装

   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 单独的日志名称,所以可以单独配置。

[netty4][netty-common]Future与Promise分析的更多相关文章

  1. Netty 源码解析(三): Netty 的 Future 和 Promise

    今天是猿灯塔“365篇原创计划”第三篇. 接下来的时间灯塔君持续更新Netty系列一共九篇 Netty 源码解析(一): 开始 Netty 源码解析(二): Netty 的 Channel 当前:Ne ...

  2. Netty异步Future源码解读

    本文地址: https://juejin.im/post/5df771ee6fb9a0161d743069 说在前面 本文的 Netty源码使用的是 4.1.31.Final 版本,不同版本会有一些差 ...

  3. Netty 中的异步编程 Future 和 Promise

    Netty 中大量 I/O 操作都是异步执行,本篇博文来聊聊 Netty 中的异步编程. Java Future 提供的异步模型 JDK 5 引入了 Future 模式.Future 接口是 Java ...

  4. Future和Promise

    Future用于获取异步操作的结果,而Promise则比较抽象,无法直接猜测出其功能. Future Future最早来源于JDK的java.util.concurrent.Future,它用于代表异 ...

  5. Future与Promise

    https://code.csdn.NET/DOC_Scala/chinese_scala_offical_document/file/Futures-and-Promises-cn.md#ancho ...

  6. Netty 核心组件 Pipeline 源码分析(一)之剖析 pipeline 三巨头

    目录大纲: 前言 ChannelPipeline | ChannelHandler | ChannelHandlerContext 三巨头介绍 三巨头编织过程(创建过程) ChannelPipelin ...

  7. Netty 核心组件 Pipeline 源码分析(二)一个请求的 pipeline 之旅

    目录大纲: 前言 针对 Netty 例子源码做了哪些修改? 看 pipeline 是如何将数据送到自定义 handler 的 看 pipeline 是如何将数据从自定义 handler 送出的 总结 ...

  8. 《深入探索Netty原理及源码分析》文集小结

    <深入探索Netty原理及源码分析>文集小结 https://www.jianshu.com/p/239a196152de

  9. C++之future和promise

    future和promise的作用是在不同线程之间传递数据.使用指针也可以完成数据的传递,但是指针非常危险,因为互斥量不能阻止指针的访问:而且指针的方式传递的数据是固定的,如果更改数据类型,那么还需要 ...

随机推荐

  1. 浏览器兼容圆角Border-radius的问题

    圆角css代码:border-radius只有在以下版本的浏览器:Firefox4.0+.Google Chrome 10.0+.Opera 10.5+.IE9+支持border-radius标准语法 ...

  2. C# sftp通过秘钥上传下载

    一.适用场景 我们平时习惯了使用ftp来上传下载文件,尤其是很多Linux环境下,我们一般都会通过第三方的SSH工具连接到Linux,但是当我们需要传输文件到Linux服务器当中,很多人习惯用ftp来 ...

  3. nmap --script http-enum,http-headers,http-methods,http-php-version -p 80 目标域

    从http服务器上收集到更多地信息 nmap --script http-enum,http-headers,http-methods,http-php-version  -p 80 目标域

  4. python3基础04(requests常见请求)

    #!/usr/bin/env python# -*- coding:utf-8 -*- import requestsimport jsonimport reimport urllib3from ur ...

  5. AD7190的小总结

    1.单次转换模式 通过配置“模式寄存器的MD2.MD1.MD0为001”,便可启动单次转换. 流程“上电 -> 单次转换 -> 省电模式 ” , 片内振荡上电需要大约1ms.   单次转换 ...

  6. java Vamei快速教程05 实施接口

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 在封装与接口中,private关键字封装了对象的内部成员.经过封装,产品隐藏了内部 ...

  7. innobackupex基于binlog日志的恢复 -- 使用mysqlbinlog恢复

    备份先做一次完整备份: innobackupex --defaults-file=/etc/my.cnf --user root --password chengce243 /data/mysqlba ...

  8. 2018.10.05 TOPOI提高组模拟赛 解题报告

    得分: \(100+5+100=205\)(真的是出乎意料) \(T1\):抵制克苏恩(点此看题面) 原题: [BZOJ4832][Lydsy1704月赛] 抵制克苏恩 应该还是一个比较简单的\(DP ...

  9. PMBOK(第六版) PMP笔记——第十章(项目沟通管理)

    PM 大多数时间都用在与干系人的沟通上.第十章有三个过程: 规划沟通管理:根据干系人的需求,制定沟通管理计划管理沟通:根据沟通管理计划发布.收集.处理信息监督沟通:确保在正确时间将正确信息传递给正确的 ...

  10. RabbitMQ使用教程(五)如何保证队列里的消息99.99%被消费?

    1. 前情回顾 RabbitMQ使用教程(一)RabbitMQ环境安装配置及Hello World示例 RabbitMQ使用教程(二)RabbitMQ用户管理,角色管理及权限设置 RabbitMQ使用 ...