一、NIO简介
NIO即Non-block I/O,非阻塞I/O,与Socket类和ServerSocket类相对应,NIO也提供了SocketChannel和ServerSocketChannel两种不同的套接字通道实现。
深入理解NIO之前呢,首先我们要了解与NIO有关的基本概念。如Buffer(缓冲区)、Channel(管道、通道)、Selector(选择器、多路复用器)
1、缓冲区Buffer
Buffer是一个对象,它包含一些要写入或者要读出的数据。在NIO类库中加入Buffer对象,体现了新库与原I/O的一个重要区别。在面向流的IO中,可以将数据直接写入或读取到Stream对象中。在NIO库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的;在写入数据时,写入到缓冲区中。任何时候访问NIO中的数据,都是通过缓冲区进行操作的。
缓冲区实质是一个数组,通常它是一个字节数组(ByteBuffer),这个数组为缓冲区提供了数据的访问读写等操作。实际上每一种java基本类型都对应一种缓冲区(除了Boolean类型)
2、通道Channel
Channel就像自来水管道一样,网络数据通过Channel读取和写入,通过与流的不同之处在于通道是双向的,而流只是一个方向上移动(一个流必须是inputStream或者OutputStream的子类),而通道可以用于读、写或者两者同时进行。
最关键的是可以与多路复用器集合起来,有多种的状态位,方便多路复用器去识别,事实上通道分为两大类,一类是网络读写的(SelecttableChannel),一类是用于文件操作的(FileChannel)。我们常使用的SocketChannel和ServerSocketChannel都是selectableChannel的子类。
3、多路复用选择器 Selector
它是NIO编程的基础,非常重要,多路复用器提供选择已经就绪的任务的能力。简单说,就是Selector会不断地轮询注册在其上的通道(Channel) 假如某个通道发生了读写操作,这个通道就处于就绪状态,会被Selector轮询出来,然后通过SelectionKey可以取得就绪的Channel集合,从而进行后续的IO操作。
一个Selector可以负责成千上万Channel通道,没有上线,这也是JDK使用了epoll代替了传统的select实现,获得连接句柄没有限制。这就意味着 我们只需要一个线程负责Selector的轮询,就可以接入成千上万个客户端。