一、IO多路复用可以简单用一句话诠释:
一个线程来处理多个 socket
更进一步地对上面那句话诠释:一个线程来调动服务器来轮流处理多个客户端发来的请求
针对 TCP 来说,服务器这边每次要服务一个客户端,都需要给这个客户端安排一个 socket
一个服务器服务多个客户端,同时就有很多个 socket
同一时刻,只有少数 socket 是活跃的(大部分情况)
这些 socket 上都是无时无刻的在传输数据么? 很多情况下,每个客户端和服务器之间的通信也没那么频繁 此时这么多 socket 大部分时间都是 静默 的,上面是没有数据需要传输的
二、IO 多路复用的 API 及常用语言的 IO 多路复用的方式
IO 多路复用 => 一个线程来处理多个 socket
操作系统,给程序员提供的机制,提供了一套 API,内部的功能都是操作系统内核实现的
Linux 上提供的 IO 多路复用,主要是三套 API
- select
- poll
- epoll
epoll 是运行效率最高的机制
C++ 可以直接使用 Linux 原生的 epoll api
java 可以使用 NIO(标准库提供的一组类,底层就是封装了 epoll)
三、简单示例(日常生活)来解释 IO 多路复用 一看就懂!
问题:
我楼下有个小摊,我们小区也有这样的小摊,然后今天晚上,我和妻子都不想做饭,于是我们商量着要在楼下小摊买点饭带回家吃
我想吃蛋炒饭
我妻子想吃肉夹馍
我女儿想吃饺子
都有什么实现方案呢?
第一种:
我自己去,先买蛋炒饭,等拿到了蛋炒饭后,再去买肉夹馍,再等肉夹馍好了后,去买饺子,等饺子好了,就全部搞定了!
效率最低的方案!!!
第二种:
我们三个人一起去,我去买蛋炒饭,妻子去买肉夹馍,女儿去买饺子,各等各的,然后都拿到后就全部搞定了
效率大大提升了,但是系统开销大了
第三种:
先去买蛋炒饭,等的过程中去买肉夹馍,还在等的过程中,去买饺子
这三份饭,哪个先做好了,对应的老板就可以喊我一嗓子,然后我都拿到后就全部搞定了!
此时就能让我一个线程同时做三件事
能高效地完成这三件事的前提是,这三件事的交互都不频繁,大部分时间都在等!!!
“对应的老板就可以喊我一嗓子” 这就叫 epoll 事件通知/回调机制
我的操作以及对应的场景就是 IO 复用!
四、IO 复用不适合的场景:
如果多个事件都是交互特别频繁的,还是老老实实多搞几个线程靠谱,一个线程就容易忙不过来