上一篇讲了阻塞式IO,在阻塞IO中,若是有大量的并发请求,势必要针对请求开启多线程,针对每个请求开启一个线程,这样每个线程的处理时间就会包含以前的T1+T2这两个等待数据的时间,白白浪费了服务器的线程资源。linux
服务器核心要作的事情是等数据到了我再作事情。服务器的线程处理时间里面只须要包含数据到了后续部分。这样最大限度的利用了珍贵的服务器线程资源,而且因为线程的处理时间中没有包含等待数据的时间,可使得线程快速释放。服务器
现实生活中的例子,餐厅,阻塞IO相似于每来一个客人我立刻分配一个厨师,让厨师等着客人点餐,而后再去作饭,厨师的工做就是作饭,可是在这个例子中,他却把时间白白浪费到了等待客人点单上。多线程
若是有新的客人来,这个时候还得再分一个厨师给他,若是高峰时候,客人太多,一个客人分配一个厨师,厨师就会不够用,可是不少厨师却不是在忙着作饭,而是在盯着客人等待菜单。厨师的利用率很是低。并发
IO多路复用的核心即是解决服务器线程包含数据等待的时间的问题。socket
引入一个观察者线程,专门去监听系统IO,若是发现有数据ready了,便分配一个线程去处理。性能
改良餐厅的模式,老板招聘一个服务员,让服务员看着客人,若是有客人点餐结束,他马上把点好的单子通知厨师,让厨师进行作饭。好比在两个客人前后到达,第一个客人点餐很快,菜也很简单,厨师小张很快就作完了第一个客人的饭。这个时候第二个客人的餐也点完了,厨师小张能够继续为第二个客人作饭,很明显,效率极大提高。
线程
多路是指多个IO输入,在本例中,是指多个客人。blog
复用的就是那个观察者线程,本例中就是那个服务员。进程
在linux中多路复用是经过epoll(相似于服务员)来实现的。epoll会监控已经链接的Socket(相似于客人),当socket对应的IO变为可读后(客人点完了菜),通知应用进程(相似于厨师)进行读取,应用进程把数据从内核复制到用户空间的过程,就相似于厨师。资源
epoll为何可以快速的监控到IO就绪,组员专门来介绍,本文暂时不作说明。select,和poll是以前的实现,epoll是最新的实现,性能最好。