NIO简介
Java NIO 是从jdk1.4开始引入的一个新的IO API ,可以完全代替标准的IO API。NIO与原来的IO有同样的作用和目的,但是使用方式完全不同,NIO支持面向缓冲区的、基于通道的IO操作,读写操作更加高效。
IO与NIO的区别:
NIO系统的核心在于:通道(Channel)和缓冲区(Buffer)。通道表示打开到IO设备(文件、套接字等)的连接,缓冲区负责暂时存放传输数据。
简而言之,Channel负责传输,Buffer负责存储。
Buffer存取数据
1 | /** |
直接缓冲区和非直接缓冲区
非直接缓冲区:通过allocate()方法分配缓冲区,将缓冲区建立在JVM的内存中
直接缓冲区:通过allocateDirect()方法分配,将缓冲区直接建立在物理内存中。可以提高效率。
1 |
|
Channel传输数据
1 | /** |
1 | // 完成文件的复制(内存映射文件) 直接缓冲区 |
对于直接字节缓存区来说,JVM会尽最大努力直接在此缓冲区执行本机的IO操作,避免每次调用基础操作系统的。一个本机IO操作之前或之后,将缓冲区的内容复制到中间的缓冲区中。
通道之间的数据传输
1 | // 通道之间的数据传输 |
分散读取和聚集写入
分散读取:将通道中读取到的数据分散到多个缓冲区中。
聚集写入:将多个缓冲区中的数据写入到一个通道中。
1 | // 分散读取和聚集写入 |
阻塞与非阻塞
- 传统的IO 流都是阻塞式的。当一个线程调用read() 或write()时,该线程被阻塞,直到有一些数据被读取或写入,该线程在此期间不能执行其他任务。因此,在完成网络通信进行IO 操作时,由于线程会阻塞,所以服务器端必须为每个客户端都提供一个独立的线程进行处理,当服务器端需要处理大量客户端时,性能急剧下降。
- Java NIO 是非阻塞模式的。当线程从某通道进行读写数据时,若没有数据可用时,该线程可以进行其他任务。线程通常将非阻塞IO 的空闲时间用于在其他通道上执行IO 操作,所以单独的线程可以管理多个输入和输出通道。因此,NIO 可以让服务器端使用一个或有限几个线程来同时处理连接到服务器端的所有客户端请求。
阻塞式IO通信
1 | public class BlockTest { |
非阻塞式IO通信
1 | public class NonBlockTest { |