1. 现象

最近在一次项目编码中遇到这么一个情况: 程序本身是一个中间处理器的角色,功能可简述为接收硬件设备的报文,然后对某些报文处理(其他报文直接转发),然后发送服务端处理;服务端处理后回复,程序接收服务端回复,然后直接转发给硬件设备。在测试时发现,硬件设备第一次发送报文,能够正常处理,但是当硬件设备第二次发送报文时,程序中Java NIO会持续触发读事件,导致服务端持续回复报文,从而设备持续收到回复报文。

2. 问题排查

由于程序中很多地方使用到线程池、队列等,一开始排查是否是这些因素导致的,但是经过仔细的控制变量的测试,发现并不是这些导致的。在这个问题上纠结了半天多,感觉崩溃的时候,决定去网上找找思路,然后看到一个同仁遇到类似问题,其中说到NIO中的边缘触发和水平触发,于是仔细看了下这两个概念:
(1) 水平触发是当就绪的fd未被用户进程处理,下一次select()查询依旧会返回,这是select和poll的触发方式。
(2) 边缘触发是无论就绪的fd是否被处理,下一次不再返回。理论上性能更高,但是实现相当复杂,并且任何意外的丢失事件都会造成请求处理错误。epoll默认使用水平触发,通过相应选项可以使用边缘触发。

由于开发、测试是在windows平台下进行的,windows中Java NIO的底层网络模型是select模型,所以其触发方式为水平触发。所以上面遇到的情况很可能是由于就绪的fd未被处理,导致每次都会返回该事件。于是沿着这个方向排查。

经过排查,最终发现了原因:由于服务端在处理读事件时,将通道中的数据读到ByteBuffer中。将数据写入ByteBuffer后,经过一系列处理,该ByteBuffer的limit和position相等了,第二次再使用这个ByteBuffer来读通道中的数据时,将无法将数据写入该ByteBuffer,即就绪fd未被处理,导致下次selector调用select()方法时,又会返回该事件。

3. 解决方法

找到问题的原因后,解决办法还是比较简单的:
(1) 如果当前ByteBuffer中的数据不完整,需要等到下次读事件的数据一起处理,那么可以在这次读完(即将数据写入ByteBuffer中,一般写完后会调用filp()等待数据被读取)后调用ByteBuffer的compact()方法;

ByteBuffer的compact()方法会将position置为limit,limit设置为capacity,这样下次处理读事件时,通道中的数据可以接着写在上一次数据的后面。

(2) 如果当前ByteBuffer中的数据是完整的,则从该ByteBuffer读完数据后,将该ByteBuffer置为null,下一次处理读事件时,重新初始化该ByteBuffer即可。

Java NIO持续触发读事件的解决方法相关推荐

  1. form的submit()方法不能触发onsubmit事件的解决方法,兼容各版本浏览器。

    form的submit()方法不能触发onsubmit事件的解决方法,兼容各版本浏览器. 参考文章: (1)form的submit()方法不能触发onsubmit事件的解决方法,兼容各版本浏览器. ( ...

  2. 工作手记之移动端中文输入法触发oninput事件的解决方法

    事件背景 工作过程中涉及到了移动端输入内容长度的限定,这就要求需要对输入过程中内容的变化进行监控和判定,以决定是否可以继续输入,所以就想着是否可以在相关输入处监听oninput事件?但是在手机端,中文 ...

  3. java开发中遇到的问题及解决方法(持续更新)

    java开发中遇到的问题及解决方法(持续更新) 参考文章: (1)java开发中遇到的问题及解决方法(持续更新) (2)https://www.cnblogs.com/LiuYanYGZ/p/6112 ...

  4. onchange监听input值变化及input隐藏后change事件不触发的原因与解决方法(设置readonly后onchange不起作用的解决方案)

    onchange监听input值变化及input隐藏后change事件不触发的原因与解决方法(设置readonly后onchange不起作用的解决方案) 参考文章: (1)onchange监听inpu ...

  5. 关于ElementUI中MessageBox弹框的取消键盘触发事件(enter,esc)关闭弹窗(执行事件)的解决方法

    关于ElementUI中MessageBox弹框的取消键盘触发事件(enter,esc)关闭弹窗(执行事件)的解决方法 参考文章: (1)关于ElementUI中MessageBox弹框的取消键盘触发 ...

  6. 苹果safari浏览器 button点击不会触发focus事件 如何解决?

    苹果safari浏览器 button点击不会触发focus事件 如何解决? 解决如下: //点击时手动focus <button id="button" type=" ...

  7. click与dblclick事件冲突解决方法

    一个DOM元素,如:div,既绑定了 click 事件,又绑定了 dblclick 事件,这两个事件分别要做独立的事情.事件处理上没有冲突,都可以各自完成各自的操作.双击的时候虽然是执行了 dblcl ...

  8. java.lang.ClassNotFoundException: com.mysql.jdbc.Driver 解决方法 java.lang.ClassNotFoundException: com.

    java.lang.ClassNotFoundException: com.mysql.jdbc.Driver 解决方法 java.lang.ClassNotFoundException: com.m ...

  9. Adobe flash cs5 的Java运行时环境初始化错误 完美解决方法

    Adobe flash cs5 的Java运行时环境初始化错误 完美解决方法 下载网络上的Adobe flash cs5 精简版(绿色版),Java运行时环境初始化时出现错误,你可能需要重装Flash ...

最新文章

  1. 在当当买了python怎么下载源代码-爬虫实战:爬取当当网所有 Python 书籍
  2. springboot情操陶冶-web配置(四)
  3. POJ1195Mobile phones
  4. 使用模板有什么缺点?如何避免?
  5. python 概率分布_python实现概率分布
  6. 8 CO配置-控制-一般控制-定义 CO 版本的分类账
  7. IPv6带给互联网的新契机
  8. 冒泡排序(一分钟懂)
  9. php搜索功能代码实列,php记录搜索引擎关键词的代码示例
  10. 【C语言】筛选法求素数
  11. arduino交互设计作品2019——害羞的郁金香
  12. 通达OA二次开发手册V12
  13. 使用ipad通过usb线连接电脑
  14. Deepin邮箱登录阿里云邮箱个人版服务器设置
  15. 【Python】在Windows 10 中,安装django-bootstrap-modal-forms
  16. python实现自动拨打电话_twilio python自动拨打电话,播放自定义mp3音频的方法
  17. mybatis处理joda datetime
  18. unity支持的模型数据格式,unity3d模型制作规范
  19. web前端的网页优化
  20. cas单点登录学习笔记 .

热门文章

  1. ActiveMQ是什么
  2. PHP聚合数据-全国车辆违章
  3. kb931125—rootsupd_Windows XP 您的时钟快了,无法建立私密连接
  4. 工作居住证办理条件及用途
  5. linux窗口切换快捷键_分配快捷键以在Linux上激活打开的应用程序窗口
  6. android 播放固定频率的声音,Android使用SoundPool播放音效
  7. 科普 | 带你了解设备振动监测常见术语
  8. jdbc 连接虚拟机mysql_JDBC 连接数据库步骤
  9. 使用 ADBLOCK PLUS 关闭百度浏览器百度热搜
  10. android studio 接口方法,Android Studio第三十期 - 介绍几种网络请求方式写法