# IO介绍

参考博客：[https://blog.csdn.net/haoyuyang/article/details/53231585](https://blog.csdn.net/haoyuyang/article/details/53231585)

**IO（BIO）与NIO的区别**

其本质就是阻塞和非阻塞的区别。

阻塞概念：应用程序在获取网络数据的时候，如果网络传输数据很慢，那么程序就一直等着，直到传输完毕为止。

非阻塞概念：应用程序直接可以获取已经准备就绪的数据，无需等待。

IO为同步阻塞形式，NIO为同步非阻塞形式。NIO没有实现异步，在JDK1.7之后，升级了NIO库包，支持异步非阻塞通信模型，即NIO2.0(AIO)。

同步和异步：同步和异步一般是面向操作系统与应用程序对IO操作的层面上来区别的。①同步时，应用程序会直接参与IO读写操作，并且应用程序会直接阻塞到某一个方法上，直到数据准备就绪（BIO）；或者采用轮询的策略实时检查数据的就绪状态，如果就绪则获取数据（NIO）。②异步时，则所有的IO读写操作都交给操作系统处理，与应用程序没有直接关系，应用程序并不关心IO读写，当操作系统完成IO读写操作时，会向应用程序发出通知，应用程序直接获取数据即可。

同步说的是Server服务端的执行方式，阻塞说的是具体的技术，接收数据的方式、状态（io、nio）。

**AIO**

在NIO的基础上引入了异步通道的概念，并提供了异步文件和异步套接字通道的实现，从而在真正意义上实现了异步非阻塞，之前的NIO只是非阻塞而并非异步。AIO不需要通过对多路复用器对注册的通道进行轮询操作即可实现异步读写，从而简化NIO编程模型。

NIO编程介绍

学习NIO编程，首先需要了解几个概念：

（1）Buffer（缓冲区）

Buffer是一个对象，它包含一些需要写入或者读取的数据。在NIO类库中加入Buffer对象，体现了新类库与原IO的一个重要区别。在面向流的IO中，可以直接将数据写入或读取到Stream对象中。在NIO类库中，所有的数据都是用缓冲区处理的（读写）。 缓冲区实质上是一个数组，通常它是一个字节数组（ByteBuffer），也可以使用其他类型的数组。这个数组为缓冲区提供了访问数据的读写等操作属性，如位置、容量、上限等概念，具体的可以参考API文档。

Buffer类型：最常使用的是ByteBuffer，实际上每一种java基本类型都对应了一种缓存区（除了Boolean类型）。

①ByteBuffer②CharBuffer③ShortBuffer④IntBuffer⑤LongBuffer⑥FloatBuffer⑦DoubleBuffer

（2）Channel（管道、通道）

Channel就像自来水管道一样，网络数据通过Channel读取和写入，通道与流的不同之处在于通道是双向的，而流只能在一个方向上移动（一个流必须是InputStream或者OutputStream的子类），而通道可以用于读、写或者二者同时进行，最关键的是可以和多路复用器集合起来，有多种的状态位，方便多路复用器去识别。通道分为两大类：一类是用于网络读写的SelectableChannel，另一类是用于文件操作的FileChannel，我们使用的SocketChannel和ServerSocketChannel都是SelectableChannel的子类。

（3）Selector（选择器、多路复用器）

是NIO编程的基础，非常重要。多路复用器提供选择已经就绪的任务的能力。简单说，就是Selector会不断的轮询注册在其上的通道（Channel），如果某个通道发生了读写操作，这个通道就处于就绪状态，会被Selector轮询出来，然后通过SelectionKey可以取得就绪的Channel集合，从而进行后续的IO操作。一个多路复用器（Selector）可以负责成千上万的通道（Channel），没有上限。这也是JDK使用了epoll代替传统的select实现，获得连接句柄（客户端）没有限制。那也就意味着我们只要一个线程负责Selector的轮询，就可以接入成千上万个客户端，这是JDK NIO库的巨大进步。

Selector线程类似一个管理者（Master），管理了成千上万个管道，然后轮询哪个管道的数据已经准备好了，通知CPU执行IO的读取或写入操作。

Selector模式：当IO事件（管道）注册到选择器以后，Selector会分配给每个管道一个key值，相当于标签。Selector选择器是以轮询的方式进行查找注册的所有IO事件（管道），当IO事件（管道）准备就绪后，Selector就会识别，会通过key值来找到相应的管道，进行相关的数据处理操作（从管道中读取或写入数据，写到缓冲区中）。每个管道都会对选择器进行注册不同的事件状态，以便选择器查找。

事件状态：

SelectionKey.OP\_CONNECT

SelectionKey.OP\_ACCEPT

SelectionKey.OP\_READ

SelectionKey.OP\_WRITE

NIO通信模型图解：

![](https://img-blog.csdn.net/20161119210915533)

（虚线表示不直接相关联）
