Java之nio学习
刚刚开始接触nio的时候有点迷惑,在网上也看过很多资料,大多都是讲了怎么用,没有个系统介绍。于是就花了点时间看看。
1、nio是java传统网络IO的升级版,nio和io的关系可以看成http协议和tcp/ip协议(升级版)
2、nio相比于io,是更精准的传输协议。具体的下面再说。
然后说说nio和io的比较
io传输直接是读取byte数组,由此产生的阻塞,缓冲区的额外开销等等问题在nio上没有的,原因如下:
首先看看nio的传输单元:java.nio包下的ByteBuffer,ShortBuffer,FloatBuffer,IntBuffer,DoubleBuffer,LongBuffer,它们都继承于Buffer,
Buffer含有4个属性,
private int mark = -1; private int position = 0; private int limit; private int capacity;
由此可见,在传输的时候,就标注好了每个传输单元的长度/容量等一系列信息,自然在接受一端无需缓冲区了,很类似http的格式,增加了报文头等),解决网络io长久以来的缓冲区的各种问题。
网络传输阻塞问题在nio的解决。
原有io在socket传输时一旦信息传送停止,等待接收的线程就会一直等待直到超时异常抛出。
nio中采用的是基于事件驱动的事件-触发的模式来避免了阻塞,或者说是反应器设计模式(可能有的人也觉得是观察者模式,的确很类似:当被被观察体改变时,所有相关的依属体都得到通知,不过观察者只限于单个事件,反应器是与多公个事件源关联)。
nio的非阻塞机制由Channel 类和Selector 类来完成,Selector是Channel的多路复用器,Channel官方解释为服务端和客户端的一种通信机制,每个 Channel 向 Selector 注册事件。当事件从客户机处到来时, Selector 将它们多路分用并将这些事件分派到相应的 Channel 。乍一看上去就是不是很熟悉?没错,很类似Socket = SocketServer.accpet(),然后分配一个新线程给对应的Socket,但是这里的Channel仅仅是作为信息传输,不能加入额外的逻辑处理。
相比于传统的网络IO,不需要用户自定义Thread来负责和客户端交互信息,只需要处理业务逻辑。
以网络传输来说,运行步骤如下
1、Channel向Selector注册
2、有请求则Selector分配Channel进行信息传输(按照Buffer的“协议”),如果某个线程在一个Channel的I/O上阻塞时,另一个线程可以关闭这个Channel(实际物理传输层的上阻塞是不可避免的)。
3、当某个Channel信息接受完整后,接受到的信息提交给用户自定义的处理模块完成业务处理,返回信息由这个Channel写回去
最后说说我认为的nio的缺点(缺点仔细想想也谈不上,主要是需要注意地方),由于加入Buffer格式,对于旧有的系统和非java.nio的系统来说,得有额外的支持。