首先说一下核心区别:
先来了解一下buffer的工作机制:
1.这一步其实是当我们刚开始初始化这个buffer数组的时候,开始默认是这样的
2、但是当你往buffer数组中开始写入的时候几个字节的时候就会变成下面的图,position会移动你数据的结束的下一个位置,这个时候你需要把buffer中的数据写到channel管道中,所以此时我们就需要用这个buffer.flip();方法,
3、当你调用完2中的方法时,这个时候就会变成下面的图了,这样的话其实就可以知道你刚刚写到buffer中的数据是在position---->limit之间,然后下一步调用clear();
4、这时底层操作系统就可以从缓冲区中正确读取这 5 个字节数据发送出去了。在下一次写数据之前我们在调一下 clear() 方法。缓冲区的索引状态又回到初始位置。(其实这一步有点像IO中的把转运字节数组 char[] buf = new char[1024]; 不足1024字节的部分给强制刷新出去的意思)推荐:250期面试题
1、这里还要说明一下 mark,当我们调用 mark() 时,它将记录当前 position 的前一个位置,当我们调用 reset 时,position 将恢复 mark 记录下来的值
2、clear()方法会:清空整个缓冲区。position将被设回0,limit被设置成 capacity的值(这个个人的理解就是当你在flip()方法的基础上已经记住你写入了多少字节数据,直接把position到limit之间的也就是你写入已经记住的数据给“复制”到管道中)
3、当你把缓冲区的数局写入到管道中的时候,你需要调用flip()方法将Buffer从写模式切换到读模式,调用flip()方法会将position设回0,并将limit设置成之前position的值。buf.flip();(其实我个人理解的就相当于先记住缓冲区缓冲了多少数据)
public void selector() throws IOException {
//先给缓冲区申请内存空间
ByteBuffer buffer = ByteBuffer.allocate(1024);
//打开Selector为了它可以轮询每个 Channel 的状态
Selector selector = Selector.open();
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);//设置为非阻塞方式
ssc.socket().bind(new InetSocketAddress(8080));
ssc.register(selector, SelectionKey.OP_ACCEPT);//注册监听的事件
while (true) {
Set selectedKeys = selector.selectedKeys();//取得所有key集合
Iterator it = selectedKeys.iterator();
while (it.hasNext()) {
SelectionKey key = (SelectionKey) it.next();
if ((key.readyOps() & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT) {
ServerSocketChannel ssChannel = (ServerSocketChannel) key.channel();
SocketChannel sc = ssChannel.accept();//接受到服务端的请求
sc.configureBlocking(false);
sc.register(selector, SelectionKey.OP_READ);
it.remove();
} else if
((key.readyOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ) {
SocketChannel sc = (SocketChannel) key.channel();
while (true) {
buffer.clear();
int n = sc.read(buffer);//读取数据
if (n <= 0) {
break;
}
buffer.flip();
}
it.remove();
}
}
}
}
最后给大家看一下整体的NIO的示意图
感谢阅读,希望对你有所帮助 :)
来源:blog.csdn.net/qq_36520235/article/details/81318189
END
题外推荐
十期推荐
【291期】你了解Log4j2中RollingFile的文件滚动更新机制吗? 【292期】Linux面试最高频的5个基本问题 【293期】面试官:你知道写时复制(Copy-On-Write)在Java中是如何被应用的吗? 【294期】面试官:谈谈你对缓存的使用和理解 【295期】面试官:已经用k8s来部署运维各个微服务的组件,是否可以不用整套微服务? 【296期】面试官:详细说说对MQ消息队列的理解以及主流MQ的优缺点 【297期】面试官:为什么在new 对象里面使用自动注入对象会报空指针异常? 【298期】面试官:如何保证token的安全 【299期】面试官:详细说一说MySQL InnoDB 中意向锁的作用 【300期】面试官:Elasticsearch 是如何做到快速检索的 与其在网上拼命找题? 不如马上关注我们~