1. 简介
NIO,全称为 Non-blocking I/O,是 JDK 1.4 及以上版本引入的新 I/O 操作 API。它主要提供了用于高伸缩性网络的缓冲支持的数据容器,支持非阻塞式的高伸缩性网络。
2. IO 和 NIO 的区别
-
IO(传统的IO):
- 面向流,阻塞的。
- 不存在缓存的概念,每次从流中读取一个或多个字节,直到读取所有字节。
- 读写是阻塞的,即当一个线程调用读写方法时,该线程会被阻塞,直到有数据被读取或写入完成。
-
NIO:
- 面向块,非阻塞的。
- 有缓冲的概念,数据被读取到缓冲区,可以前后移动,增加了处理过程的灵活性。
- 非阻塞模式,一个线程请求读取数据,如果目前没有数据可用,就什么都不会获取,不会阻塞线程,提高了并发度。
3. NIO 的核心实现
3.1 Channel
-
通道的实现类:
FileChannel:用于读取、写入、映射和操作文件的通道。DatagramChannel:通过 UDP 读写网络中的数据。SocketChannel:通过 TCP 读写网络中的数据。ServerSocketChannel:可以监听新进来的 TCP 连接。
-
通道的特性:
- 通道可以同时进行读写,而流只能读或写。
- 通道可以实现异步读写数据。
- 通道可以从缓冲读数据,也可以写数据到缓冲。
3.2 Buffer
-
缓冲区(Buffer):
- 缓冲区是一个可以写入数据的内存块,也可以从中读取数据。
- 数据总是从通道读取到缓冲区,或者从缓冲区写入到通道。
- 缓冲区提供了一组方法,使得更轻松地使用内存块。
-
Buffer 的常用方法:
flip():将 Buffer 从写模式切换到读模式,重置 position 为 0,limit 设置为之前的 position。clear()和compact():清空缓冲区。put()和get():向缓冲区写入数据和从缓冲区读取数据。
3.3 Selector
-
Selector:
- 一个组件,可以检测多个 NIO channel,看读或写事件是否就绪。
- 多个 Channel 以事件的方式可以注册到同一个 Selector,用一个线程处理多个请求成为可能。
4. 总结
- NIO 提供了更灵活、更高效的 IO 操作方式,特别适用于需要处理大量连接的场景,如网络编程。
- 通过 Channel、Buffer、Selector 这些核心概念,NIO 实现了非阻塞、面向块的 IO 操作。
- NIO 的使用可以提高程序的并发性,降低资源消耗。