NIO简介

什么是NIO?

在java.nio包下都是与NIO有关的类,这些类是java1.4中引入的。NIO(non-blocking IO),有的地方也称之为 new IO。NIO的作用跟之前IO(也叫作BIO)的作用是一样的,可以进行本次磁盘IO和网络IO,只不过使用方式完全不同,且NIO可以最大限度的满足 Java 程序 I/O 的需求,当连接数量多的时候,效率会更高一些,需要注意的是NIO没有屏蔽不同操作系统之间的差异,如果要用于生产环境下的话,建议使用NIO的框架,入netty,mina等。

传统的IO操作

NIO和BIO对比

BIO是 面向流的, 每次可以从流中读取n个字节, 只能由前往后读取数据。NIO 是面向缓冲区的, 把数据读到一个缓冲区中, 可以在缓冲区中向前/向后移动,增加了程序的灵活性。

在网络io时,BIO是阻塞的,NIO是非阻塞的。线程在进行read或者write的期间不能做其他事情,比如执行socket.read的时候,服务器如果没有发送数据的话,线程会一直阻塞。而NIO中可以将socket设置为非阻塞的。

NIO核心组件

  • Buffer(缓冲区)

    本质就是一个数组,我们可以向其写入数据,亦可读取数据。主要负责数据的存取。

  • Channel(通道)

    主要作用是进行数据的传输,是双向的,读写均可,一个Channel对应一个Buffer

  • Selector(选择器)

    可以检查多个Channel,能够确认哪些通道已经准备好进行读取或者写入,这样子的话,一个线程就可以操作一个Selector,从而管理多个Channel了。

在 NIO 中, 所有的数据都需要通过 Channel 传输, Channel可以直接将一块数据映射到内存中。Channel是双向的, 不仅可以read, 还能write。 程序不能直接读写Channel通道,Channel 只与 Buffer 缓冲区交互。

BIO是阻塞的, 在读写数据时,线程阻塞,即在数据操作完毕之前,线程不能做其他的任务。NIO 不是线程阻塞的. 当线程从 Channel 中读写数据且Channel中没有可用的数据时,线程不阻塞,可以做其他的任务。

下图展示了NIO核心组件之间的关系。1个线程可以操作一个Selector,1个Selector可以管理多个Channel,每个Channel中可以包含多个Buffer,这样就相当于是1个线程可以操作多个Buffer来传输数据了