epoll是个好东西好多地方都在直接或间接的用,nginx用event库用nio用你用我用大家用。LT模式省心ET模式牛掰,处理得当效率那真是杠杠的,C、C++的用法可以参考“项目”通用库https://git.oschina.net/gonglibin/GlbLib-1.0.0中的封装,也可以参考“代码片段”中的用例https://git.oschina.net/gonglibin/codes/kev675liw8unz3j4psft134。由于一个潜在的项目迁移计划导致未来存在基于java技术路线中涉及线程池大并发长(短)连接的业务,所以一个框架就显得特别重要,兵马未动粮草先行。其实不同的业务包含各自不同的应用场景,就通信而言其实差别有时候还是挺大的,同样TCP连接,有的长有的短,有的求多应少,有的求少应多,还有一问一答的,更有一言不合就shutdown的,对底层资源的管理不上心有时候真不行,大半夜没起过夜绝对不算老司机。

说说nio踩过的坑吧,下面列举的仅仅是让发动机托底的大坑,其中崴脚的小坑更是不计其数,首先打开地址https://git.oschina.net/gonglibin/codes/2jagu36pq7dwsc1eylkr916。首先注意一点的是nio的许多操作不是线程安全的,用不对各种坑有的踩了。大致思路首先创建TCP服务,构造里建线程池,主进程里给selector对象画个圈圈,这个对象的所有操作限制在listen方法里,把对业务的处理全部浸泡在读事件中,为啥读完不注册写信号让写事件处理呢,一会后面说吧,要是忘了千万别提醒我。

坑一,cli.register(sel, SelectionKey.OP_READ, ByteBuffer.allocate(TU_SERSIZE)),在注册新连接的时候顺带把allocate的buffer赋值给SelectionKey对象的attachment,接下来read并判断读取长度,不大于零和对端一起关闭,否则把SelectionKey对象往线程池里一派发就完事了,流程自己继续跑它自己的路,代码看起来简洁潇洒大气木毛病,正嘚瑟着问题来了,对端一关闭傻眼了,新请求直接把attachment擦除了,所以还是别顺带了,老老实实给每个任务开个buffer吧。

坑二,这些年搬砖一直追求精益求精对资源少占少用,C、C++一个套接字底层对应两块buffer,一读一写井水不犯河水相安无事,ByteBuffer对象是环形buffer,通过flip方法实现读写缓存的逆转,把position游标值和limit提交值一变轻松搞定,好是好但在线程池里维护一个连接上的各个buffer就够费劲的这还非要把读写合并一堆儿,真考验人呀,加锁呗,行是行就是显得low。

坑三,把SelectionKey对象的实例作为线程入口参数派发,表面看没毛病,但在完成各个事件处理以后重新注册监听事件的时候线程间同步又成了问题,其实这个坑已经解答了上面的疑问,读写分离按需注册固然完美,但每个线程的执行时间是不同的,CPU时间片调度也只能相对均衡,保不齐谁早点谁晚点,一个close操作秒完,那边任务才跑一半,咔嚓一下就把注册的监听事件给改了,结果这边的注册失效了,傻了吧唧还等呢,左等不来右等不来结果下班了。

坑四,SocketChannel对象关闭以后把SelectionKey实例的valid记做false,打标记倒是无所谓啦,不过无效的对象是不是就别再放在监听集合里处理是不是好点呀,免得每次还要判断,不判断就抛出一个异常,你看人家C库epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)设置EPOLL_CTL_DEL清理的干干净净,或许这么玩有人家自己的道理吧,相信别人这么做是有道理的。

把接收缓存和频道对象作为入参传给线程池进行任务处理,保证每次请求都能被唯一的指派,强调服务的一对一特性,处理完流程内部直接返回了,能做成读写异步自然好呀,不过写这个框架是有私心的,业务指向十分明确,其他的需求还是另起炉灶或许更好一些。最后还是要强调一下,不同的业务对通信方式的要求不尽相同,所以一个框架解决不了所有问题,还是应该具体问题具体分析。

难得一本正经的写个东西浅显地剖析一个不是问题的问题,口号喊起来:励斌出品,必是精品,欧耶!

把Java的nio坑逐个踩一遍相关推荐

  1. java 线程执行完就会回收吗_Java线程池技术Executors的这个坑你踩过吗?

    线程池技术是Java的一大特性,如果我们想要编写高并发.高吞吐的程序,线程池的技术使用是必须的.对于很多程序员来说,多线程和线程池技术都了然于胸,基本原理和使用都数量掌握,分分钟可以写出一个生产消费者 ...

  2. Java 的这些坑,你踩到了吗?

    前言 中国有句老话叫"事不过三",指一个人犯了同样的错误,一次两次还可以原谅,再多就不可原谅了.写代码也是如此,同一个代码"坑",踩第一次叫"长了经验 ...

  3. 阿里技术|Java 的这些坑,你踩到了吗?

    阿里妹导读:日常开发中总会遇到各种各样的"坑",如何提前规避呢?本文将分享 Java 开发中容易遇到的一些坑,并给出详细的问题解析和避坑方法. 前言 中国有句老话叫"事不 ...

  4. mysql int 转string_mysql的这些坑你踩过吗?快来看看怎么优化mysql

    什么是mysql? 如果你的回答是关系型数据库,那就会显得有些浅薄.我们平时工作中肯定会用到mysql,但是谈到mysql,就不能只说增删改查. 接下来我们从另一个角度认识一下mysql(其实不仅仅是 ...

  5. 理解Java的NIO

    同步与阻塞 同步和异步是针对应用程序和内核的交互而言的. 同步:执行一个操作之后,进程触发IO操作并等待(阻塞)或者轮询的去查看IO的操作(非阻塞)是否完成,等待结果,然后才继续执行后续的操作. 异步 ...

  6. 【Java】NIO中Selector的select方法源码分析

    该篇博客的有些内容和在之前介绍过了,在这里再次涉及到的就不详细说了,如果有不理解请看[Java]NIO中Channel的注册源码分析, [Java]NIO中Selector的创建源码分析 Select ...

  7. java之NIO(Channel,Buffer,Selector)

    java之NIO 1 什么是NIO Java NIO (New IO,Non-Blocking IO)是从Java 1.4版本开始引入的一套新的IO API.NIO支持面向缓冲区的.基于通道的IO操作 ...

  8. java List 常见坑

    java List 常见坑 数组转化list int[] a = {1,2,3}: List list = Arrays.asList(a); 如上代码,期望转化为有三个元素的 list,结果发现,l ...

  9. JAVA之NIO按行读写大文件,完美解决中文乱码问题

    JAVA之NIO按行读写大文件,完美解决中文乱码问题 参考文章: (1)JAVA之NIO按行读写大文件,完美解决中文乱码问题 (2)https://www.cnblogs.com/jpfss/p/89 ...

最新文章

  1. 设计模式(创建型模式)——单例模式(Singleton)
  2. 3检测人头_基于人头检测技术客流统计摄像头及管理平台
  3. 权限组件(6):权限分配的角色管理
  4. 移动端页面(响应式)
  5. mysql如何撤销上一条指令_mysql命令行,多行命令时如何取消/返回修改前边的命令...
  6. Android闹钟程序周期循环提醒源码(AlarmManager)【转】
  7. layui的table实现,strust2+layui+jsp
  8. 线性代数与MATLAB2
  9. flutter初体验之基础控件知识
  10. 如何在Mac上使用预览在PDF上打字?
  11. 团队开发之个人博客一
  12. Java证书工具keytool用法总结
  13. 数据分析——实习僧数据分析岗招聘信息分析
  14. lae界面开发工具入门之介绍九--lua脚本组件篇
  15. Oracle EBS 接收事务处理类型 rcv_transactions transaction_type
  16. 关于脑电波的黑科技,离我们生活还有多远。
  17. java中隐函数求导法则_隐函数求导法则
  18. seo文章伪原创技巧(你不知道的伪原创文章处理技巧)
  19. php匹配字符串中的url并替换为超链接
  20. ThreeJS FBXLoader 加载3D文件,材质消失,已解决

热门文章

  1. java无法注册监听器_(1507—79)在Java事件处理中,一个组件只能注册唯一的监听器对象。...
  2. 移动端适配之雪碧图(sprite)背景图片定位
  3. day-14 常用API
  4. cad批量打印_这就教你如何用CAD进行批量打印
  5. 【Python从零到壹】Python模块介绍与使用
  6. jsplumb 点击节点或者连线高亮显示
  7. linux ctrl z 的区别,linux中ctrl+z和ctrl+c的区别
  8. html5seo优化,HTML 5会如何影响我们的SEO优化
  9. linux 常用命令之运行.sh文件
  10. css改火狐滚动条样式_css布局系列1——盒模型布局