I/O 类型
阻塞 I/O:用户线程发起 I/O 操作后,内核在检查数据过程中用户线程一直阻塞,直到内核将数据复制到用户线程;
data = socket.read();
非阻塞 I/O:用户线程发起 I/O 操作后,可以马上得到内核返回,若返回值说明数据未到则稍后用户线程再发起 I/O 操作,用户线程需要轮询内核;
while(true) {data = socket.read();if(data == true) {// 内核数据已来,处理数据break;} else {// 内核数据未来,用户线程可以进行其他工作}}
多路复用 I/O:使用一个 Selector 线程在内核中不断轮询,在有 I/O 数据来的时候才通知用户线程进行 I/O 操作,由于只管理 I/O 的轮询,因此业务操作转发给其他线程处理;
- 信号驱动 I/O:用户线程发起 I/O 操作后,为该 socket 注册一个信号,内核准备好数据后发送信号到用户线程来调用 I/O 中的数据;
异步 I/O:用户线程发起 I/O 操作后,内核直接返回一个状态说明是否请求成功,之后是信号驱动 I/O 的流程;由于发起请求和数据读取都在内核中完成,期间用户线程不需要等待。
Java NIO
NIO 与 I/O 区别
I/O 面向 Stream,NIO 面向 Buffer:Stream 中无法前后移动数据; NIO 是从 Channel 读到 Buffer 或者从 Buffer 写入 Channel 的过程,可以前后移动数据,避免粘包、拆包等情况,在网络不可靠情况下好用;
I/O 阻塞式,NIO 非阻塞式:I/O 调用
write()或read()时需要阻塞;NIO 通过 Selector 监听 Channel 上的变化,有数据时使用 Buffer 读,没数据时执行其他操作,写数据时异步将 Buffer 的数据写到 Channel 上,用户线程无需等待。NIO 核心
Selector
核心是多路复用 I/O 中的 Selector 线程,监听的是 Channel 上的事件(连接打开或数据到达)。

Selector 工作模式Channel 与 Buffer
Buffer 是个容器,用于存储 Channel 来的数据和将数据发到双向流 Channel,C/S 架构中的流程是:Client -> ClientBuffer -> ClientChannel -> ServerChannel -> ServerBuffer -> Server。
Channel:
- UDP:
DatagramChannel; - TCP:
SocketChannel(客户端)和ServerSocketChannel(服务端); - 文件:
FileChannel。
- UDP:
- Buffer:
ByteBuffer、IntBuffer、CharBuffer、LongBuffer、DoubleBuffer、FloatBuffer、ShortBuffer(基本数据类型的 Buffer)。
Reactor
单线程模型

Reactor 单线程模型
- 模块
- Client:NIO 客户端,向服务器发起 TCP 连接并发送数据;
- Acceptor:与 Client 建立连接;
- Dispatcher:接收 Client 数据并以
ByteBuffer的形式发送到 DecodeHandler; - DecodeHandler:解码器,读取 Client 的数据,对消息进行解码、处理、应答;
- EncodeHandler:编码器,将返回给 Client 的数据编码并写入 Channel。
- 流程
- Acceptor 接收 Client 的 TCP 请求并建立连接;
- Dispatcher 将收到的消息写入
ByteBuffer并分配到 DecodeHandler 进行处理; - 消息处理后使用 EncodeHandler 将响应消息返回。
- 总结



