Netty inEventLoop方法?异步回调?Promise?
文章目录
inEventLoop
一直对这个方法不是很理解,众所周知是判断当前线程是不是在当前的EventLoop中对应的那个线程?
一个channel对应一个且只对应一个EventLoop,一个Channel对应一个且只对应一个Pipeline,Pipline中包含handler(也是context),当前的Handler被Channel调用,那什么时候执行这段代码的线程不是channel对应的那个EventLoop中的线程?
EventExecutor中最关键的是inEventLoop方法,用于判断一个线程是否是EventExecutor内部那个线程,EventExecutor和EventLoop都是单线程实现。inEventLoop的主要使用场景是,当IO变化时,通过channel关联的pipeline会触发对应的事件,这些事件对应的执行pipeline中的处理链中handler的回调方法,
每个handler添加到pipeline都可以指定自己的EventLoop,如果没指定,默认使用要添加的pipeline关联的channel注册到的EventLoopGroup中的某个EventLoop。所以channel通过pipeline调用handler时,如果handler没有单独指定EventLoop,那inEventLoop就会返回true,他俩由同一个线程处理,直接调用handler。如果handler单独指定了EventLoop,inEventLoop就会返回false,channel调用handler时就把要调用的方法封装到Runnable里,然后添加到handler指定的EventLoop的任务队列里,稍后会由对应的EventLoop中的线程执行。
来自:https://www.jianshu.com/p/d39ff4c98c5f
至于代码分析就不贴代码了,没有什么特别的,关键是情况的分析。
自己画了个图方便理解,当然肯定还有不对的地方,理解的不是很好,有问题希望提出共同进步!
所以会有下面两种情况
在handler中:
executor.inEventLoop()?
当前executor是channel对应的那个eventLoop,而inEventLoop中的currentThread是handler自定义的eventLoop,是不相等的。所以是false,false的时候将handler中的回调封装成task放到自己对应的eventLoop的任务队列中
这就是异步
当前的channel相当于是主线程,主线程想要回调,发现当前的handler有自己的处理线程,那么就把回调方法封装成task给他自己的Executor中的queue中,他自己去执行吧,我该干嘛干嘛去了。
为什么返回Promise
阿西,实在不想贴代码
平常用户代码习惯这么写:
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ChannelFuture future = ctx.writeAndFlush("test data"); future.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { if (future.isSuccess()){ System.out.println("写出成功"); }else{ System.out.println("写出失败"); } } }); }
为什么writeAndFlush返回future,下面通过future调用addListener?
在writeAndFlush方法中返回了promise,也就是future
在addListener方法中有一个isDone方法
然后isDone0
判断result状态,这个result状态就是DefaultPromise中的,在writeAndFlush中flush也能修改这个状态,所以是在writeAndFlush和addListener中相同的。
Promise继承自Future,Future中有isSuccess方法
所以在operationComplete方法中能够执行future.isSuccess(),即这个
promise(也就是futrure)是writeAndFlush和addListener的一个桥梁,分享着当前是否能够回调的状态(是不是写完了)
这理解其实和JDK JUC中的Future是一个意思了:
promise(也就是futrure)中的result也是一个状态值,如果writeAndFlush完成了,设置值success,并且去
主动唤醒,或者在addListener中
主动唤醒。
区别就是Future中是通过get方法
被动唤醒的,所以时机可能不是那么的准确。
另外jdk中的futrue方法是通过get阻塞进行的,runnable通过run生产数据,Future通过get获取数据,FuturetTask被两者共享,继承自他们两个,拥有了run和get这两个功能,在
自导自演,run中执行callable的call方法,执行完成设置可执行标志,没有完成则标志还是未完成的,get方法一直阻塞,可是如果已经生产好了,而没有get呢?所以在Netty中通过listener这种方法更加精准的添加了监听,能够第一时间回调。
拾遗
什么是异步?
是否要等待一个操作的完成?
什么是阻塞?
是否要等待一个数据准备好?
当然在Netty中还有一个比较有意思的:
WriteAndFlush和addListener方法,如果是异步的,在writeAndFlush之前,完成了AddListener,那么在WriteAndFlush执行完write有异常回调,或者,执行完flush回调operationComplete的时候,设置为了Success,是可以放心回调的。
可是如果是两个方法如果是同步执行,当然异步执行也可能,writeAndFlush执行完了,result设置为了Success,但是AddListener还没有添加,那要怎么回调?operationComplete还没有准备好呢。通过看源码能够知道notifyListenersNow的时候,先判断listeners(其实就是listener)是不是没有,没有直接return了,那不就意味着这次wirteAnfFlush事件没有回调了? 其实在AddListener方法中,会进行一次判断,判断当前的result是不是Success,是的话就会进行一次回调。
代码分析略。
还有ByteBuf的缓存和命中也应该细细体会。
声明:
笔者本身还是一个小白,只看到了冰山一角,不一定完全正确,如果文中存在严重的错误,还请不吝指出,不仅利于自己的修正,同时也减少他人产生对于知识的误解。
- 点赞
- 收藏
- 分享
- 文章举报
- Linux Yum安装mysql的数据库迁移目录
- linux无法正常关闭Tomcat,8005端口未启动
- 电力运维保障体系
- Linux文本处理三剑客之sed
- 四行shell脚本实现zabbix_server的高可用
- clickhouse安装和入门
- kali linux 2020.1b安装与配置
- 安装Docker-Win10环境-图解轻松学Docker&K8S
- ELK搭建与使用详解
- 又一起 BGP 劫持事件,影响全球 200 多家云服务和 CDN 提供商 – 运维派
- ApacheFTPServer的SSL模式用脚本命令的方式连接(五)
- linux常用命令归纳
- 基于压力测试工具kylinTOP构建虚拟用户自身请求的并发模型
- linux环境下java程序打包成简单的hello world输出jar包示例
- windows/linux环境python3出现pip is configured with locations that require TLS/SSL, however the..不可用的解决方法
- 图说大型网站的技术架构
- Docker网络模式与配置Docker自定义网络(bridge模式)
- 维护你的请求队列,处理token异常
- hive四种排序order by,sort by,distribute by,cluster by的区别
- 如何给软件加上一个数字签名