IO模型
大家熟悉的IO模型:BIO、NIO、IO多路复用、AIO这四种常见的IO模型
下面给大家一一解析,市面上的一些文章都是生搬硬套名词和概念,我用现实例子给大家举个例子
同步的阻塞(BIO)和非阻塞(NIO)的区别
在讲IO模型之前,我们需要先来清楚阻塞和非阻塞的概念
-
阻塞IO(BIO)
线程发起IO请求后,一直阻塞IO线程,直到缓冲区数据就绪后,再进行下一步操作
例如你去一家奶茶店,你跟店员点了一杯奶茶,然后你就一直站在台前(这个服务员只能服务你一个),直到你点的奶茶做好送到你手上了,你才离开,然后第二个人才能点单(如果服务员只有一个的话)。
如果说服务员有两个,那同时只能有两个人点到奶茶,并且都拿到了奶茶后才会给到后面的人进行点单
-
非阻塞IO(NIO)
线程发起IO请求后,立即返回,非阻塞指的是,用户线程不用原地等待IO缓冲区数据就绪,可以进行其他操作,对比阻塞IO,用户线程在IO缓冲区数据就绪之前是不可以进行其他操作的,看图也可理解。
例如你去一家奶茶店,你跟店员点了一杯奶茶,然后你从队伍前方走开,给下一个人进行点单,也就是说此时的服务员可以服务多个人,而你需要不断的定时检查自己的奶茶做好了没有(服务员不会喊你)
同步非阻塞(NIO)和异步非阻塞(AIO)的区别
可能会有人问,没有异步阻塞IO吗?是的没有,都异步操作了是没有阻塞一说的
NIO的同步非阻塞看上面的图(右边那个)
AIO的异步非阻塞看下面这张图
光看这个图,什么东西啊,根本不会,讲的啥啊,先给大家讲讲AIO的概念
在NIO实现中 ,需要用户线程定时轮询 ,去检查IO缓冲区数据是否就绪,占用应用程序线程资源,其实轮询相当于还是阻塞的,并非真正解放当前线程(例如奶茶店,你还是要在那检查自己奶茶好了没有),因为它还是需要去查询哪些IO就绪。
在**AIO实现中,**用户线程只需要告诉内核,当缓冲区就绪后,通知我或者执行我交给你的回调函数。
上面的说法可能不够直观,再以奶茶店举例子
-
NIO
例如你去一家奶茶店,你跟店员点了一杯奶茶,然后你从队伍前方走开,给下一个人进行点单,也就是说此时的服务员可以服务多个人,而你需要在奶茶店门前,不断的定时检查自己的奶茶做好了没有(服务员不会喊你)
-
AIO
例如你去一家奶茶店,你跟店员点了一杯奶茶,然后你从队伍前方走开,给下一个人进行点单,也就是说此时的服务员可以服务多个人,而你不需要在奶茶店前等了,也不需要定时检查自己的奶茶到底做好了没有,你可以去旁边的服装店看衣服,如果你的奶茶好了,服务员会通知你,你的奶茶做好了可以拿了,就好比现在你是手机点单,你的奶茶做好了,手机会有提示一样,而NIO是你得主动去问好了没有
NIO和IO多路复用的区别
IO多路复用这个概念想必大家都不陌生,在Redis的Reactor网络模型中就是IO多路复用的典型例子
IO多路复用是基于NIO的基础进行优化的
IO多路复用干讲概念,不好形容,得有个对比,就以NIO进行对比,还是以奶茶进行举例
-
NIO
例如你去一家奶茶店,你跟店员点了一杯奶茶,然后你从队伍前方走开,给下一个人进行点单,也就是说此时的服务员可以服务多个人,而你需要在奶茶店门前,不断的定时检查自己的奶茶做好了没有(服务员不会喊你)
-
IO多路复用
例如你去一家奶茶店,你不再是跟店员点了一杯奶茶了,你是用手机选择你要的奶茶然后付款,可以想象一下,NIO是需要排队的跟店员点单,IO多路复用是不用排队的,谁先手机点到单,我就响应谁,注意不要把IO多路复用和AIO弄混了,IO多路复用还是需要你在奶茶店门前等,不断的定时检查自己的奶茶做好了没有(服务员不会喊你)
总结复盘
有人可能会以现实为基础来想,IO多路复用为什么要以NIO为基础进行优化呢?我还是要在奶茶店门前等,还是要检查自己的奶茶做好了没有,没人主动通知我,AIO不是很好吗,在现实中效率和体验感是最好的
但是朋友我们得清楚一个问题,越是效率好体验好的,想要用代码实现起来就越是复杂,而且经过测试,AIO的性能和NIO的性能没什么差别,而AIO的代码复杂度是很复杂的。