概念
NIO出现之前,Java 使用传统Socket实现基本的网络通信功能。当没有客户端对服务器发起请求时,会在accept()阻塞。同时简历连接后read()、write()也会阻塞。
处理多个连接,需要采用多线程的方式,阻塞会导致线程进行上下文切换,是的程序的效率很低。NIO采用非阻塞的方式实现网络通信,提高了效率。
实现原理
NIO通过Selector、Channel和Buffer实现非阻塞的IO操作。
传统IO基于字节流和字符流进行操作,而NIO基于Channel和Buffer(缓冲区)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。Selector(选择区)用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个线程可以监听多个数据通道。
Channel
Channel是一个双向非阻塞通道,通道两边可以进行数据的读写操作
Buffer
一个Buffer对象是固定数量的数据的容器。其作用是一个存储器,或者分段运输区,在这里数据可被存储并在之后用于检索。尽管缓冲区作用于它们存储的原始数据类型,但缓冲区十分倾向于处理字节。非字节缓冲区可以在后台执行从字节或到字节的转换,这取决于缓冲区是如何创建的。
Selector
Selector实现了用一个线程来管理多个通道(采用复用与解复用的方式,即多个流合并成一个流,一个流分成多个流),类似于一个观察者。
Selector内部实现原理:对所有注册的Channel进行轮询访问,一旦轮询到一个Channel有注册时间发生,就通过SelectionKey的方式通知开发人员对这个Channel进行数据读写处理