Netty 学习之 NIO / BIO / AIO 基础知识 (二)

in with 0 comment

NIO

好吧,NIO 就是 new IO, 是java对原有IO流API的替代API,属于非阻塞型IO。 对于NIO,需要知道几个概念,Channel,Buffer,非阻塞,Selectors:

Buffer

使用Buffer读写数据一般遵循以下四个步骤:

  1. 写入数据到Buffer
  2. 调用flip()方法
  3. 从Buffer中读取数据
  4. 调用clear()方法或者compact()方法

BIO

可以理解为block-io,即阻塞型IO,就是当你调用read时候,只有有数据才会返回,而没有数据时,是不会返回只会阻塞等待的。 传统的Java Socket就是这样一种机制,有数据才会返回,否则会一直阻塞。

比如我们使用Socket进行与服务端通信,默认情况下服务端需要对每个请求建立一个线程等待请求,而客户端发送请求后,先咨询服务端是否有线程响应,如果没有则会一直等待或者遭到拒绝请求,如果有的话,客户端的线程会等待请求结束得到服务端返回信息后才继续执行。

AIO

AIO在java1.7之后新加入进来的,可以理解为nio2.0,异步非阻塞型,重要的有以下几个类

AsynchronousSocketChannel
AsynchronousServerSocketChannel
AsynchronousFileChannel
AsynchronousByteChannel

它的伸缩性则更强了,在开始的NIO中,虽然是非阻塞的,但是还是需要轮训才知道那个通道数据可用。 而在AIO,并不需要selector去轮训了。 在AIO中,调用方法会立即返回,并且会告诉调用者,这次请求已经开始了,系统会使用另外的资源或者线程来完成 这次调用操作,并且在完成时候会通知调用者(比如回调方法)。

总结

从实现来看,传统IO与NIO确实存在不小的区别。 1、传统IO是一次读取4(或其他,有规律)个字节,而NIO,则是一次读取多个,直接存入buffer(在c++层面就是读取多个,而不是一次读取一个再在Java层面拼凑出Buffer)。 2、NIO在读取时,如果传入的不是directBuffer,则最终读取时,还是通过一个临时directBuffer读取,最后放入传入的buffer中。 3、传统IO读取经过以下2个步骤:

NIO和AIO区别

二者在操作系统层面对文件的操作是一致的,均是以buffer为单位传送,而在通信模型上有区别: NIO通常采用Reactor模式,AIO通常采用Proactor模式。AIO简化了程序的编写,stream的读取和写入都有OS来完成,不需 要像NIO那样子遍历Selector。Windows基于IOCP实现AIO,Linux只有eppoll模拟实现了AIO。Java7之前的JDK只支持NIO和BIO,从7开始支持AIO。

关于Reactor模式和Proactor模式的一些参考

https://www.cnblogs.com/me115/p/4452801.html https://www.jianshu.com/p/b7723c489e1c 个人认为 Proactor模式的处理效率在某种情况下要快一些,毕竟是牺牲了更多的资源。