Java nio 初体验

Java的nio是jdk5推出的东西,距现在已经五六年了。我虽然曾经使用过Mina(一个使用事件驱动的nio框架)做过一些项目,但实际上对nio的了解还是很模糊,只是知道它的特点是“非阻塞”。 

近期打算研究一下Netty(它跟Mina很像,是同一个作者的作品),所以先研究下Nio。网上的中文资料相当少,大多讲得不清不楚,给的示例代码更是看得人头晕。好在群友“羊八井”推荐了我一本好书:《Java network programming 3rn edition》,它的第12章就是专讲nio的。这本书写得不错,详细而清晰,把重点都讲到了。我花了三四个小时,把这一章读完,基本上对nio有了一个比较感性上的认识。 

nio是new IO,它的特点是“非阻塞”相对于之前的阻塞IO,最大的好处是提高了性能。只要抓住两点:“非阻塞”与“性能”,nio就好理解了。 

以前使用Java进行socket编程时,等待客户端连接的accept()和读取数据的read()方法,都是“阻塞”的。“阻塞”的意思就是说,这两个函数都是非常固执的,一旦调用,所在线程就会卡在那里,直到取到了数据,或者超时,或者出错。意味着一个线程一次只能做一件事情。如果客户端连接只有一个,这种方式倒十分简便,但一旦有多个连接,服务器就必须用多个线程分别处理。当连接比较多(比如上千时),就会有大量的时间浪费在线程间的切换上,性能比较差。对于像web server这样的程序来说,是难以接受的。 

nio是非阻塞的,它的accept()和read()方法,调用后马上返回,线程不会卡住。这样我们就可以在一个线程中,处理多个连接(当然也可以使用更多的线程,更充分地利用cpu)。那么,我们如何知道有连接来了,或者拿到数据了呢?答案是轮询,判断返回值,办法虽笨,但是有用。 nio还是“事件驱动”的,这与“非阻塞”正好搭配。我们可以给每个连接注册想要监听的事件,如accept, connect, read, write,然后就去做别的事。如果没事可做,就轮询,调用selectKeys()方法检查当前发生的事件。当我们监听的事件发生了(比如监听了read事件,并且有数据可读时),即可得到对应的SelectKey对象。我们可以从该对象身上拿到对应的连接,做想做的事情,比如读数据写数据,注册新的监听事件等。 该“性能”了。

nio为了提高数据交换的性能,提供了一些buffer类,用于缓存读取的数据及输出的数据。这些buffer长度固定,并且用一些属性如position, limit, mark等标示当前可用的数据,以及一些方法clear(), flip(), rewind(), mark(), reset(), compact()等,改变这些属性。这里有些复杂,一定要理解清楚,才不会用错。但理解起来也不难,因为它搞这么复杂就是为了复用数据,为了复用肯定要有一些方法来记录哪些数据被使用了,哪些未被使用。这样在read和write时,才能正确拿到可用的数据。nio中,所有需要交换数据的地方,都在用buffer,所以相关操作一定要弄明白,不然寸步难行。 

最后就是nio中几个重要的概念:Channel, Selector, SelectionKey, Buffer。

Channel就像是门,Selector是看门的,SelectionKey是事件记录,而Buffer是送货的推车。 整个流程是这样的

首先我们在墙上装几个门(Channel),然后请一个看门人(Selector)过来,告诉他要看哪几个门(注册),还要记录下哪些情况。然后我就去干自己的事了,过一会儿过来看看,对看门人说:把你的记录本给我看看。如果是空的,就还给他,接着干自己的事。如果有记录(SelectionKey),就一一查看:A门有人送货,B门有人提货,C门有客上门。这时可能会用到推车(Buffer)来装货卸货。处理完这一批事件后,我把这些记录撕掉(key.remove()),还给看门人,告诉他还要记录哪些新情况(重新注册)。然后我再去做其它事,过一会儿再回来看看。。。 

从这里可以看出,nio还是比较底层的,属于基础设施。因为它虽然可以告诉我们发生了哪些事件,但是不能给每个事件设置回调函数,必须手动轮询。所以就有了如Mina、Netty这样的基于nio的框架。它们最大的作用,就是抽象出多个事件,让我们设置对应的回调函数。之前我还需要过一会儿过来问问看门人,而现在,我只需要在一开始给看门人交待好“发生了什么事情,你就去做什么事”,然后就可以什么也不用管了。 Nio的重点差不多就这样了,剩下的就是要熟悉那些api的使用。原理相比以前的阻塞io要复杂了一点,但是api却复杂不少。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

欧米优

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值