什么是NIO?
NIO所在的包是java.nio。其中的n表示non-blocking。但是实际上我们可以把它理解成nio=net+io,因为NIO包实现了网络通讯和io的联合功能,并且将他们结合发挥到极致,实现了完美的非阻塞通讯功能。如图所示:
为什么会有NIO?
因为普通的socket通讯存在着I/O问题----阻塞通讯,并且分析传统的解决方法----线程池的优缺点,进而引进NIO的解决方案。
1基于Socket通讯的存在的问题----I/O阻塞通信
经典的网络服务器的结构的通讯过程:
方框内的操作会循环执行,并且监听连接、读取数据、写入数据这些操作都是阻塞的。在其ServerSocket操作的具体如下:
1 Socket socket = ss.accept(); //这里是阻塞的
2 BufferReader br = new BufferReader(new InputStrameReader(socket.getInputStream()));
PrintWriter pw = new PrintWriter(socket.getOutputStream());
//读写数据
String line;
while(line==br.readline()!=null){ //读阻塞
os.println(line); //写阻塞
os.flush();
}
在Jdk1.4之前解决这个问题是利用线程池的方法来解决的,服务器启动的时候创建一个线程池,当监听到客户端连接时,就为客户端从线程池取出一个线程,当客户端断开连接时,该客户端就会将该线程归还到线程池中,以提高线程池的使用效率。
虽然线程池可以使服务器处理多个连接,但是每个线程拥有自己的栈空间并且浪费大量的cpu时间,消耗比较大,而且很多时间是浪费在阻塞的I/O操作上,没有有效的利用CPU。
所以最新解决方式是----NIO 非阻塞通信
如何用NIO?
首先需要理解NIO的四个核心框架
1 缓存Buffer:它是包含数据且用于读写的线性表结构。其中还提供了一个特殊的类用于内存映射文件的I/O操作。
2 字符集Charset:提供了Unicode字符串影射到字节序列及逆影射的操作。
3 通道Channel:包含Socket、File和Pipe这三个管道,它实际上是双向交流的通道。
4 选择器Selector:将多元异步I/O操作集中到一个或多个线程中。
(下次会详细的解释这四种核心框架)
然后了解一下NIO通道编程:简单了解一下四种通道类编程(具体下次详细介绍)
1 文件通道FileChannel:用于实现对文件的读取、写入、锁定和映射
2 Socket通道SocketChannel:实现基于Socket通道
3 ServerSocket通道ServerSocket:实现基于ServerSocket通道
4 数据报通道DatagramChannel:实现基于DatagramChannel通道
NIO的非阻塞I/O机制是围绕选择器和通道构建的。Channel类表示服务器和客户端之间的一种通讯机制。与反应器模式一致。Selector类是Channel的多路复用器。Selector类将传入客户机请求的多路分用。并且将他们分派到各自的请求处理程序,实现客户端请求事件的非阻塞监听
在椭圆区域中,Selector监听器负责轮询客户端的连接、读取和写入事件,这些事件执行都不会被阻塞,并且提高执行效率,NIO读取和写入事件都使用了缓存区。