NIO的由来,为什么需要NIO(一)

 

 

引出下面一段故事......

 

kenny:io包现在已经这么优雅完美了,别改坏了!

 

kyle:不不不,我们肯定遵循开闭原则(对修改关闭,对扩展开放),所以不会随意修改io的,那io接口有什么问题没有?

 

kenny:除了有人说它过度设计之外,好像没什么呀,当你了解装饰模式后你会觉得它还是很好理解的啊。

 

kyle:你不认为网络原因或者其他原因碰到阻塞的io会使程序可用性大大降低吗?

 

kenny:这个我知道,比如我去读取文件中的一行数据:

当一个线程在执行这段代码, 遇到readLine()方法的时候, 需要等待数据从硬盘进入内存, 这个线程就会被阻塞,   当然我觉得这也没啥, 很正常啊, 大家不都是这么编程的吗?

 

kyle:不, 有很多人反映了这个问题, 大家想把它改成非阻塞的, 也就是说调用了readLine()方法以后,立刻就返回, 线程就可以干别的事情去了。

 

kenny:为什么要去干别的事情? 这个线程不就是为了读数据吗?   好,就如你所说, 现在变成了非阻塞的, 调用了readLine()以后, 线程可以执行后面的代码了, 那这个线程岂不还得做个轮询操作,看看数据是不是已经读好了?

这样一来,代码多丑陋啊, 不符合我一贯的美学原则, 还不如我原来的阻塞方式呢,我觉得你的要求不可思议。

 

kyle:要是你的线程打开了成百上千个文件呢?  你这种阻塞的方式,只能按照文件1, 文件2, 文件3......   顺序的读取这么多文件,太慢了.  如果是非阻塞方式, 你可以同时发起成百上千个读操作(读操作是由DMA(Direct Memory Access,直接内存读取),不消耗cpu,非用户态操作。关于用户态和内核态下一篇会讲到),  然后在那个循环中检查, 看看谁的数据准备好了,就读取谁的, 效率多高啊。

 

kenny:谁会那么傻, 用一个线程打开这么多文件?肯定开多个线程呀。

 

kyle:那~你听说过服务器端的Socket编程吗?

 

kenny:我当然知道, 我还知道这个情况: 一个socket连接来了, 就创建一个新的线程或者从线程池分配一个线程去处理这个连接。

 

kyle:那要是并发连接数太多了怎么办?

 

kenny:那就多创建线程呗。

 

kyle:每个线程都会占用内存空间, 数量多了系统受不了,线程之间的切换也是个要命的开销啊(线程切换需要cpu在用户态和内核态之间切换,cpu对于各线程变量或数据的存储读取需要消耗大量时间)。

 

kyle看着kenny沉默不语若有所思的样子,赶紧称热打铁补了一句:

所以大家呼唤非阻塞的方式啊,   让一个线程管理成百上千个sockcet连接,就像管理多个文件一样,这样就不用做线程切换了。

 

kenny:我似乎有点明白了, 正常情况下, 在某一个时刻, 不是每个socket 都有数据读写, 很多时候都是空闲的,所以完全可以用轮询的方式来查看那些socket可以读写, 进行操作就可以了。

 

kyle:好吧, 你想怎么改?

 

总结:

网上关于nio和io的比较都是在比速度,小码农翻墙查了下外网,发现老外关注的nio并不是速度问题,关于读取速度面向缓存或者是bio的字节读取还是nio的块级读取,这些都是附加功能,并不是核心,核心是为了高可用,即可扩展。

       选用宗量还应考虑很多东西:

  • 客户的生命时间?短期还是长期?

  • 每个客户预计的数据量?很多小块或几块巨大的块?

  • 预计会同时连接多少客户端?

  • 您使用的是什么操作系统以及您使用的JVM是什么?这两个因素分为线程和轮询成本。

简单来说,(长连接)高并发,低带宽,高扩展,考虑nio;(短连接)低并发,高带宽,考虑bio即普通io;

加我微信进技术交流群,各大教学资源免费领取,大厂内推!关注订阅号:一只可爱的小码农,不定时推送高质量学习文章。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值