netty之wakeup详解
有关wakeup变量的使用有一下几个地方(这里只使用netty普通任务举例,不讨论定时任务)
部分1,NioEventLoop.select()
if (hasTasks() && wakenUp.compareAndSet(false, true)) {selector.selectNow();selectCnt = 1;break;}int selectedKeys = selector.select(timeoutMillis);selectCnt ++;if (selectedKeys != 0 || oldWakenUp || wakenUp.get() || hasTasks() || hasScheduledTasks()) {break;}
部分2 NioEventLoop.run()
select(wakenUp.getAndSet(false));if (wakenUp.get()) {selector.wakeup();}
部分3 NioEventLoop.wakeup()
protected void wakeup(boolean inEventLoop) {if (!inEventLoop && wakenUp.compareAndSet(false, true)) {selector.wakeup();}}
1,2是reactor线程进行操作的方法 3是用户线程操作的方法
方法三比较好理解,就是在添加完一个任务后,去修改这个wakeup变量,然后去唤醒这个reactor线程
首先关注2,值得注意的是getAndSet返回的是修改之前的值,但是在这个select(wakenUp.getAndSet(false))之后又调用了一次selector.wakeup(); 为什么要这样做呢???
举例:
情况一
wakeup此时为默认值,但是现在用户线程在select(wakenUp.getAndSet(false)) 之前 修改wakeup为 true,调用了 wakeup()
此时传入select(wakenUp.getAndSet(false))的参数oldwakeup为 true ,wake的最新值,笔者称为newwakeup 这里为 false
因为用户线程调用了wakeup(),所以阻塞的select 方法不会阻塞
所以成功的没有进过阻塞进入break 因为没有阻塞,这种情况我称为唤醒成功
情况二
但是现在用户线程在select(wakenUp.getAndSet(false)) 之后 修改wakeup会失败,wakeup()不会调用
select(wakenUp.getAndSet(false))的参数oldwakeup为 false,newwakeup 为true
在部分1中if (hasTasks() && wakenUp.compareAndSet(false, true)) 这个判断会进入,然后调用了一次selectNow(),然后就break了
没有阻塞,唤醒成功
以上两中情况,针对的是第一次遍历执行
下面进入第二次遍历执行
当上面的情况被唤醒后,就会来到 if (wakenUp.get()) 这个判断,这里如果是被唤醒过来的,这里就会为true,又调用了一次wakeup
那么当再次进入oldwakeup为true,newwakeup为false,所以又重复了第一次遍历中的第一种情况,那么为什么要这么做???
加入netty在第二次遍历的时候又进来的一个任务呢?此时是没有办法调用到wakeup()这个方法的,因为调用这个方法之前有一个判断
wakenUp.compareAndSet(false, true),这个判断不会通过,而部分2中的wakeup()就是解决这个情况的
对于后面的遍历,如果没有设计到唤醒操作,那么oldwakeup 和 newwakeup都是false,netty就会进入正常的轮询了
那么现在又有一个问题,为什么需要使用到wakeup这个变量?
通过这个变量的类型可以知道 wakeup 是 AtomicBoolean,所以一定是为了解决并发问题的,如果说多个线程都需要唤醒操作本来是需要执行多次wakeup()这个操作的,但是wakeup()是个耗时的操作,所以使用到AtomicBoolean的compareAndSet(expect, update)方法,使得多次wakeup()都合并成一个wakeup()
netty之wakeup详解相关推荐
- Netty之Bootstrap详解
本文来重点说下Bootstrap 文章目录 概述 Boostrap类 引导客户端和无连接协议Booststrap 引导服务端ServerBootstrap 本文小结 概述 在了解 ChanelPipe ...
- 六个月离职空档期获得足够时间反思自我+常见Netty面试题详解
前言 疫情期我离职了,在这个时间离职也是很无奈.但这次的经历却让我有了一个认真反思的机会. 回顾前两年的工作经历,每天忙忙碌碌,看似解决了很多问题,也积累了很多经验,但实际都是一些浅层次的东西,只不过 ...
- Netty 教程 – ByteBuf详解
ByteBuffer存在的问题 ByteBuffer是JDK1.4中提供的java.nio.Buffer, 在内存中预留指定大小的存储空间来存放临时数据,其他Buffer的子类有:CharBuffer ...
- Netty 教程 – 解码器详解
TCP以流的方式进行数据传输,上层的应用为了对消息进行区分,往往采用如下方式 固定消息长度,累计读取到长度和定长LEN的报文后,就认为读取到了个完整的消息,然后将计数器位置重置在读取下一个报文内容 将 ...
- Netty之ByteBuf详解
1. ByteBuf的创建 在Netty中,有一个比较常见的对象ByteBuf,它其实等同于Java Nio中的ByteBuffer,但是ByteBuf对Nio中的ByteBuffer的功能做了很作增 ...
- netty 之 telnet HelloWorld 详解
2019独角兽企业重金招聘Python工程师标准>>> 依赖工具 Maven Git JDK IntelliJ IDEA 源码拉取 从官方仓库 https://github.com/ ...
- Netty详解(五):Netty TCP粘包 拆包
1. 概述 无论是服务端还是客户端,我们读取或者发送消息的时候,都需要考虑TCP底层的粘包和拆包机制.下面我们来通过Netty来详解TCP底层的粘包和拆包机制. 2. TCP底层的粘包和拆包机制 TC ...
- netty系列之:netty中各不同种类的channel详解
文章目录 简介 ServerChannel和它的类型 Epoll和Kqueue AbstractServerChannel ServerSocketChannel ServerDomainSocket ...
- netty系列之:netty中的Channel详解
文章目录 简介 Channel详解 异步IO和ChannelFuture Channel的层级结构 释放资源 事件处理 总结 简介 Channel是连接ByteBuf和Event的桥梁,netty中的 ...
- netty系列之:netty中的ByteBuf详解
文章目录 简介 ByteBuf详解 创建一个Buff 随机访问Buff 序列读写 搜索 其他衍生buffer方法 和现有JDK类型的转换 总结 简介 netty中用于进行信息承载和交流的类叫做Byte ...
最新文章
- [置顶] 决策树绘图(二)
- P1634 禽兽的传染病
- SimpleDateFormat 格式图
- Chrome Native Client 原理
- 围棋经典棋谱_秀秀老师:茶艺师也要学好围棋
- 万丰科技机器人排名_2020年全国机器人企业数量大排名(省份榜|9月)
- 实现前后端数据交互方法汇总
- 如果数据库也有一个元宇宙,应该会是什么样子?
- 今天的天气好热哦!!!
- 前端汉字encode_js编码转码中文
- 服务器怎么开启lldp协议,修改服务器lldp的mac地址
- 迅雷 应版权方要求,文件无法下载 解决方法
- “离职同事在工作群抢红包被踢”:学会退群,是职场人的基本修养
- 世界互联网大会马云演讲实录
- C#利用QRCode动态生成自定义二维码图片
- 分步:配置 IPAM 以管理 IP 地址空间
- 【控制】鲁棒性 H2 H无穷
- wordpress二次元主题
- 网友形容丑的50种搞笑方式(转载)
- 【渝粤题库】陕西师范大学200551 英语语音
热门文章
- Vue移动端H5手势缩放滚动拖拽插件Easyscroller
- 百度快照投诉技巧案例分析百度快照就是这样刷出来的
- 剑指 Offer(C++版本)系列:剑指 Offer 10- II 青蛙跳台阶问题
- web onblur string
- 《雍正皇帝》文化专有词翻译策略的研究现状(Baker)
- arcgis server发布自定义打印模板及利用ArcGIS API javascript使用自定义打印服务打印地图
- MyEclipse8.5开发环境配置,SVN插件安装问题(转载)
- WordPress添加站点图标与底部备案信息
- python的for语句打印金字塔图形_python打印星号金字塔的方法
- Windows用户账户控制详解