IO模型之NIO快速理解

IO模型之NIO快速理解

什么是NIO?
NIO是一个非阻塞的就是说,他在accept()的时候不会阻塞,在read()的时候也不会阻塞,和之前的BIO不同。
假设有一万个连接,如果是BIO那内核就必须抛出1万个线程去处理,但是NIO确不用,他可能只需要几百个就行。
为什么NIO可以做到这样呢?是因为NIO的3大核心。

//NIO : non-blocking IO 这是在Socket网络 内核机制中
//NIO : new IO 这是在jdk中的称呼 核心{channel、bytebuffer、selector(多路复用器的一个)}

jdk里NIO的3大核心{channel、Bytebuffer、selector}

一、单线程的NIO(channel、Bytebuffer)

在之前是得到一个socket对象,然后得到一个输入流一个输出流,但是这个channel提供读的能力和写的能力,而且还带一个ByteBuffer,这里Bytebuffer不做太细的解说了,后面还会记录的。

既可以从通道里把数据读到ByteBuffer,还可以在ByteBuffer里把数据加工处理后在写到通道里,如下图所示:
在这里插入图片描述

补充说下:一般一个channel(通道)对应一个ByteBuffer,但是多个通道对应一个ByteBuffer也可以不过要进行窜行化的处理。

下面先来讲一下单线程版本的NIO,就是只有一个线程在处理连接和数据的读写,但是不会阻塞原因是什么呢?看下面的示例代码。

NIO其实主要是通过设置***configureBlocking(false)***来做到非阻塞的。
服务端会一直循环的去看有没有客户端连上来,如果有连上来的就放到一个集合里,如果没有就返回-1,然后进行下一次循环,所以不会阻塞。
在这里插入图片描述
放到集合里去之后,然后会去遍历这个集合如果在通道里读到东西了就放到ByteBuffer里去没有的话就返回-1,读完数据的时候要filp()翻转一下,这个是为了让上图中position的这个复位,ByteBuffer里的数据用完之后要清空ByteBuffer给下一个用客户端用。
在这里插入图片描述

缺点分析:上面这种存在一个很大的问题就是资源的浪费,比如说当有C10K(一万个)个连接时,每次都要去循环一次,但是不一定有客户端连上来而且也不一定有数据读,而且每个客户端读一次数据的复杂度是O(1)那一万个的复杂度就是O(C10K),假设C10K中只有2个要读,那资源就是很浪费。
如果把连接比做路的话,这个就好比是100条路,每条路长10米,然后都要你自己去跑,去看哪条路有或者然后去卸货,那这样的话就会很麻烦,那怎么解决这个问题呢? 这个时候就引出了一个多路复用器的概念,这个是什么意思呢,就是说你可以把这所有的路一下子全交给一个调用由这个调用去告诉你那条路需要读了,这个多路复用器就像是收费站一样。
那么这个多路复用器是什么呢?在操作系统内核里是什么呢?
{select、poll、epoll}

二、多路复用器(selector)

里面注意一下IO是同步的处理是异步的Futuer
在这里插入图片描述

不管NIO还是BIO都要有一个listen状态的server,第一步把server交给select,select是一个系统调用,调select的时候就把6fd传到内核去了,内核就会告诉你有没有人建立连接给你返回,select会告诉你6上有事了,然后会给你返回一个7fd,然后把7fd也放到select里去,6里面关注有没有人连接,7里面关注有没有数据到达,这个时候read的复杂度就不是O(n)的了,假设有两个人告诉你要读就是O(2),这个减少的是什么呢是程序调内核、程序调内核的次数,也就是用户态和内核态的一个切换,就像之前一样每条路你都要跑回来在跑过去看,但是现在不用了,现在只需要跟收费站说下,有车需要卸货告诉我一下。这个就是多路复用器。

(1)、先讲单线程版的selector

就是只有一个线程去处理一下图里的事情。
在这里插入图片描述

(2)、多线程版的selector

2.1 混合模型

什么是混合模型?就是有一个线程既充当boss也充当worker。
在这里插入图片描述

2.1 主从模型

什么是多线程的selector呢?相比前面的当线程的做的事情就是一个线程去处理连接数据的读写,而这里的多线程就是有一个线程相当于一个管家(boss),它不做别的,只负责accept()客户端连接,而其他线程就是工作者,会处理客户端的数据的读写等事件。

这个具体是在 做的呢? 就是当listen完之后,会把server注册到boss的selector上,然后每隔一段时间,这个boss就会去轮询一次看看有没有要连接的客户端,如果有的话就把它连上去,然后放到一个队列里去,然后就由这个worker去取出来将它注册到worker的selector上。

当然这个selector也可以有多个,原理是一样的。其实netty就和这个已经有点像了。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值