NIO 与 java NIO
阅读说明
以下内容仅为个人学习总结,并不代表权威解释。
如有谬误还请在留言区斧正。
概述
NIO 不等于 Java NIO
liunx 内存架构
首先回顾一下 liunx 中一切及文件。
liunx 内存架构分为: 用户态 与 内核态 两种。
内核态 可以访问用户态的数据。
用户态 不可以访问 内核态的数据。
只有内核态才可以操作如网卡 磁盘等硬件资源,仅能通过回调函数(syscall)得到内核态的返回值。
实现I/O,并不是Java的能力,而是操作系统内核提供的能力。其它高级语言也是如此。
liunx五种I/O
- 阻塞I/O:IO操作需要再内核态中彻底完成后才返回到用户态。
- 非阻塞I/O:非阻塞是指IO操作被调用后立即给用户一个状态值,无需等到I/O操作彻底完成。需要用户线程再每个通路上,各自不断轮询I/O状态,来判断是否有可处理的数据。
- I/O多路复用:将连接中的可读可写事件剥离出来,使用单独的线程来对其进行管理。
- 信号驱动:不常用 待完善
- 异步I/O:不常用 待完善
内核提供了三种多路复用的架构
select 由数组实现一个I/O执行对列,存放I/O链接,存放数量有限。需要通过轮询找到就绪的I/O。
poll 采用链表实现,取消了I/O个数限制。依然需要通过轮询来找到就绪的I/O。
epoll 分离出一个epoll_wait 链表存放已就绪的I/O链接。
阻塞与同步
阻塞与非阻塞 的区别为,用户态调用内核态I/O操作的方式。
同步与异步 指用户线程与内核的交互方式。
同步:用户线程发起I/O请求后需要等待或轮询内核I/O操作完成后才能继续执行。
异步:用户线程发起I/O请求后仍然继续执行,当内核I/O操作完成后会通知用户线程,或者调用用户线程注册的回调函数。
结论:阻塞I/O,非阻塞I/O,I/O多路复用,都属于同步调用。只有实现了特殊API的AIO才是异步调用。
java NIO
java NIO 不是 非组塞I/O。是从1.4 版本后,提供的一套可以替代标准的java I/O 的new API 由散部分组成:
Buffer 缓冲区
Channel 通道
Selector 选择器。使用系统epoll机制实现,是由系统内核提供的能力。
使用步骤:
获取channel
设置非阻塞
创建多路复用器 selector
channel 和 selector 做关联
根据selector返回的channel状态处理逻辑
//开启一个channel
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
//设置为非阻塞
serverSocketChannel.configureBlocking(false);
//绑定端口
serverSocketChannel.bind(new InetSocketAddress(PORT));
//打开一个多路复用器
Selector selector = Selector.open();
//绑定多路复用器和channel
serverSocketChannel.registor(selector,SelectionKey.OP_ACCEPT);
//获取到达的事件
while(selector.select() > 0){
Set< SelectionKey > keys = selector.keys();
if ( selectionKey.isAcceptable() ) {
//处理逻辑
}
if ( selectionKey.isReadable() ) {
//处理逻辑
}
}