NIO基本介绍
同步和异步,同步指的是应用程序会直接参与IO读写操作,用阻塞或者长轮询的方式来获取数据。异步指的是IO交给操作系统,完成IO读写后通知程序,程序直接拿走数据。
- BIO:同步阻塞式IO,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。 Socket/ ServerSocket
- NIO:同步非阻塞式IO,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。 SocketChannel/ ServerSocketChannel
- AIO(NIO.2):异步非阻塞式IO,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理。
- Buffer 缓冲区
- Channel 管道
- Selector 多路复用器
NIO基本概念
Buffer几个基本类型,ByteBuffer,CharBuffer,ShortBuffer,IntBuffer,LongBuffer,FloadBuffer,DoubleBuffer。缓冲区是为了存放数据
Channel主要用于读写数据
Selector轮询管理Channel,在多路复用器中为各个管道和状态找到对应处理方法,采用事件驱动的思想来实现的。
(就是开个线程Selector来轮询控制Channel,当Channel有变化的时候,就去判断Channel状态来进行开启新的线程处理具体IO操作)
注意:
- seletor.select();在Select线程的主循环中是阻塞的,只有来具体的事件才会驱动下去,比如新的连接,Channel有新数据等
- ServerSocketChannel.accept();是为了接入新的客户端连接到selector
NIO java 启动流程
1) 首先是先创建ServerSocketChannel 对象,和真正处理业务的线程池
2) 然后给刚刚创建的ServerSocketChannel 对象进行绑定一个对应的端口,然后设置为非阻塞
3) 然后创建Selector对象并打开,然后把这Selector对象注册到ServerSocketChannel 中,并设置好监听的事件,监听 SelectionKey.OP_ACCEPT
4) 接着就是Selector对象进行死循环监听每一个Channel通道的事件,循环执行 Selector.select() 方法,轮询就绪的 Channel
5) 从Selector中获取所有的SelectorKey(这个就可以看成是不同的事件),如果SelectorKey是处于 OP_ACCEPT 状态,说明是新的客户端接入,调用 ServerSocketChannel.accept 接收新的客户端。
6) 然后对这个把这个接受的新客户端的Channel通道注册到ServerSocketChannel上,并且把之前的OP_ACCEPT 状态改为SelectionKey.OP_READ读取事件状态,并且设置为非阻塞的,然后把当前的这个SelectorKey给移除掉,说明这个事件完成了
7) 如果第5步的时候过来的事件不是OP_ACCEPT 状态,那就是OP_READ读取数据的事件状态,就去进行IO操作
BIO和NIO区别
- BIO面向流,NIO面向缓冲
- BIO阻塞,NIO非阻塞
BIO一个连接一个线程,NIO一个请求一个线程