1.关于NIO、BIO

  BIO blocking IO

  NIO non-blocking IO (因为是JDK1.4之后推出的也有称为 new IO,感觉前者更贴切吧)

  经过一段时间的学习才发现,原来NIO、BIO并不是由上层的处理模式决定的,只是一般来说,BIO的通信处理模式底层的IO是阻塞的(blocking),而NIO的通信处理模式是的底层IO是非阻塞的(NIO non-blocking),底层的IO的特性当然也会影响和决定上层的设计,所以之前习惯性的就认为NIO就是说的NIO的通信处理模式(可能多数刚了解的都会这样理解吧),说什么NIO就是用一个线程来处理多个请求,不再像BIO那样,针对每一个请求都单独创建一个线程,所以NIO效率比BIO高等等。当时的理解确实太过浅显,现在把自己当前的理解记录一下,当然也参考了不少网上的资料。

2.BIO和NIO的区别:

  BIO: 阻塞IO,底层使用的是阻塞IO模型,面向流,流意味着单向性,而且BIO面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方。此外,它不能前后移动流中的数据。通过JDK的源码InputStream中的read方法的注释可以看到,读取数据的时候会发生阻塞 (见下方代码)直到:1.有数据可读2.数据读取完毕3.发生异常,同理可见OutputStream的write()方法的注释也是一样的,会一直阻塞直到:1所有字节发送完毕2.发生异常。这意味着当网络传输比较缓慢的时候,读取输入流的乙方的通信线程将被长时间阻塞,如果输入流的一方需要一分钟才能把1K的数据发送完,那么读取的一方的IO线程也会被阻塞一分钟。同理,如果读取一方的网络缓慢不能及时从TCP的缓冲区中读取数据,这将会导致发送方的的Window Size不断减小,直到为0,双方处于keep-Allive状态,消息发送方将不能再向TCP缓冲区写入数据,直到TCP缓冲区的Windw Size大于0或者发生IO异常。由于Socket IO会阻塞,可以为每一个Socket创建一个Thread,实现多并发,但是这样的系统开销和资源浪费都太大,不是合理选择,可以使用线程池进行缓解,但大量连接的情况下,也应该会比较慢。

read方法的注解

zabbix模型模块_读取数据

  NIO:非阻塞,底层使用的是IO复用模型(同步非阻塞),面向缓冲区,Java NIO的缓冲导向方法略有不同,数据读取到一个它稍后处理的缓冲区,需要时可在缓冲区中前后移动。这就增加了处理过程中的灵活性。但是,还需要检查是否该缓冲区中包含所有您需要处理的数据。而且,需确保当更多的数据读入缓冲区时,不要覆盖缓冲区里尚未处理的数据。

  NIO的主要三个核心模块:Selector(选择器),Channel(通道),Buffer(缓冲区)。Selector是选择器,Channel(Socket通信的通道)需要注册到选择器上,并且多个通道可以注册到一个选择器上面,这样可以使用一个线程就能管理多个通道,避免了BIO的问题,效率高出很多,而且减少了系统的开销。Selector可以轮询调用select(),这个方法会阻塞(但是也可以指定阻塞时间,到达时间后会立即返回)。当注册的某个通道准备好要进行IO操作时,这个便返回已选择键的个数,此时通过selectedKeys获得已选择的键(SelectionKey),通过SelectionKey可以关联到对应的Channel,然后就可以进行相关的IO操作了,另外,NIO的数据读和写使用的都是 Buffer,Channel从Buffer中读取数据或者将数据写入到Buffer中。