BIO/NIO/多路复用/Selector/select/poll/epoll

前言

进行总结的初衷是没搞明白linux下的select/poll/epoll与java下nio的selector多路复用器的关系,于是对知识点进行了梳理。
先上结论,selector多路复用器算是对linux下的select/poll/epoll进行封装,selector可以i有多种实现,linux系统下默认使用epoll的实现方式。

BIO模型

https://www.jianshu.com/p/138847d5cafd

BIO即为阻塞IO的意思,通常我们讲BIO的时候都会和服务器模型配合着讲,在实际应用中讲会更好理解。大家看下面的代码,估计在大家初学java网络编程的时候用的都是这个模型:

img

什么是BIO,NIO?他们和多路复用器有啥关系?

只要没有客户端连接上服务器,accept方法就一直不能返回,这就是阻塞;对应的读写操作道理也一样,想要读取数据,必须等到有数据到达才能返回,这就是阻塞。

我们还可以站在阻塞的基础上思考一下,为什么服务器的模型要设计成来一个客户端就新建一个线程?

其实答案很简单,当来了一个客户端创建连接后,如果不给客户端新分配一个线程执行服务器逻辑,那么服务端将很难再和第二个客户端建立连接。

就算你把客户端连接用集合保存起来,通过单线程遍历集合的方式去执行服务器端逻辑也是不行的。因为如果某个客户端连接因为读写操作阻塞了,那么其他客户端将得不到执行。

image-20210327175250825

优点

每个连接创建一个线程,实现了一个服务器连接多个客户端

缺点:

1.每处理一个请求就要new一个线程,而cpu是不会停止的,时间片轮调度各个线程切换(系统计时器发出时钟中断,调度程序停止该进程运行并把进程放到就绪队列末尾),上下文切换浪费时间,并且线程多消耗内存。并且太多系统调用(用户态到内核态)。系统调用:socket监听端口,客户端accpet,创建线程,客户端读取都是系统调用

2.很多线程其实是在等数据(阻塞),是一个无用的线程

没用多路复用的NIO模型

如果说服务器只有很少的人用,那么上面那段bio的代码其实挺好的,但问题在于互联网蓬勃发展,随着服务器访问人数的增加,这样的服务器模型将会成为瓶颈。

我们以一种C10K的思想去看待上面这段服务器代码。如果我们客户端的连接数增加了10K倍,那么就意味着要创建10k个线程,单单创建线程就是一项不小的开销了,再加上线程之间要来回切换,单机服务器根本就扛不住这么大的连接数。

那既然瓶颈是出在线程上,我们就考虑能不能把服务器的模型变为单线程模型,思路其实和之前说的差不多,用集合保存每个连接的客户端,通过while循环来对每个连接进行操作。

之前我们说了这样的操作瓶颈在于accept客户端的时候会阻塞以及进行读写操作的时候会阻塞,导致单线程执行效率低。为了突破这个瓶颈,操作系统发展出了nio,这里的nio指的是非阻塞io。

也就是说在accept客户端连接的时候,不需要阻塞,如果没有客户端连接就返回-1(java-NULL),在读写操作的时候,也不阻塞,有数据就读,没数据就直接返回,这样就解决了单线程服务器的瓶颈问题。示例代码如下:

img

优点:

相比于BIO&#x

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值