游戏电视苹果数码历史美丽
投稿投诉
美丽时装
彩妆资讯
历史明星
乐活安卓
数码常识
驾车健康
苹果问答
网络发型
电视车载
室内电影
游戏科学
音乐整形

别挠头了!我教你什么是BIO,NIO,AIO

  什么是网络IO模型?
  网络IO模型指的是程序在进行网络通信时所采用的IO(InputOutput)方式。目前比较常见的有如下几种方式:
  1。BIO:BlockingIO即同步阻塞式IO
  2。NIO:NoBlockingIO即同步非阻塞式IO
  3。AIO:AsynchronousIO即异步非阻塞IO(常见但是开发的时候一般不用)
  什么是BIO?
  先看一段代码:BIO网络IO模型服务端代码publicclassServer{publicstaticvoidmain(String〔〕args)throwsIOException{创建ServerSocket,并绑定端口号ServerSocketserverSocketnewServerSocket(8080);while(true){阻塞等待客户端连接SocketsocketserverSocket。accept();读取客户端发送的数据,如果没有数据可读或者读数据的过程中会一直阻塞InputStreamissocket。getInputStream();byte〔〕buffernewbyte〔1024〕;intlenis。read(buffer);StringmsgnewString(buffer,0,len);System。out。println(Receivedmessagefromclient:msg);发送响应给客户端,如果没有数据可读或者读数据的过程中会一直阻塞OutputStreamossocket。getOutputStream();os。write(Hello,Client!。getBytes());关闭socket连接socket。close();}}}
  BIO网络IO模型客户端代码publicclassClient{publicstaticvoidmain(String〔〕args)throwsIOException{创建Socket,并连接服务端SocketsocketnewSocket(localhost,8080);向服务端发送数据OutputStreamossocket。getOutputStream();os。write(Hello,Server!。getBytes());读取服务端响应的数据InputStreamissocket。getInputStream();byte〔〕buffernewbyte〔1024〕;intlenis。read(buffer);StringmsgnewString(buffer,0,len);System。out。println(Receivedmessagefromserver:msg);关闭socket连接socket。close();}}
  这就是经典的BIO模型下的客户端和服务端网络连接。从服务端的代码中可以看到主要有两个地方存在阻塞:
  1。服务端等待客户端连接的时候阻塞
  2。进行读写的时候,数据没有准备好就会阻塞(比如客户端一直不发数据)
  对于第一种情况的阻塞,只会让accept()所在的线程做不了其他事情,但不会影响客户端的连接。
  但是如果读写时候发生阻塞,那么其他的客户端要连接服务端,就会出现无法连接的情况。因为在一个while循环中阻塞住就不会进入下一次循环。
  针对读写阻塞,无法连接多个客户端的情况,一种比较容易想到的方案是把读写放到其他线程。
  这样读写就不会阻塞while循环了,也就不会影响其他客户端连接服务器了。
  代码如下:publicclassBIOServer{privatestaticfinalintPORT8080;publicstaticvoidmain(String〔〕args)throwsIOException{ServerSocketservernewServerSocket(PORT);System。out。println(ServerstartedonportPORT);while(true){Socketclientserver。accept();System。out。println(Acceptedconnectionfromclient。getRemoteSocketAddress());多线程方式处理读写操作newThread(newClientHandler(client))。start();}}}classClientHandlerimplementsRunnable{privateSocketclient;publicClientHandler(Socketclient){this。clientclient;}Overridepublicvoidrun(){try{byte〔〕buffernewbyte〔1024〕;intlen;while((lenclient。getInputStream()。read(buffer))0){StringrequestnewString(buffer,0,len);System。out。println(Receivedrequest:request);StringresponseHellofromserver;client。getOutputStream()。write(response。getBytes());client。getOutputStream()。flush();}client。close();System。out。println(Connectionclosedbyclient);}catch(IOExceptione){处理异常}}}
  每次一个链接过来都会把要读写的操作单独开一个线程,这样while就不会被读写阻塞,可以允许多个客户端链接。
  但是要注意,这里读写虽然不阻塞while所在的线程,依旧会阻塞新开辟的线程。
  比如A客户端链接到了服务器,于是服务器给它开辟了一个线程A。
  可是该客户端一直不发数据,那么线程A则一直会被阻塞在哪里(此时线程什么也没干,还占着资源)。
  这个模型被称为BIO的原因就是accept(),read(),write()会发生阻塞。
  另外因为读写阻塞的存在,新创建的线程就会被阻塞而无法释放。如果并发量比较大的情况下就会有大量的线程被创建。
  默认情况下Java中一个线程需要分配1M的内存空间。这对服务器的资源造成了很大的浪费。
  大佬们意识到阻塞问题的严重性,于是捣鼓出了NIO模型,专注于解决阻塞问题。
  那BIO用线程池行吗?
  线程池是可以限制创建线程的多少。但是只限制达不到目的,因为并发量比较大的情况下,一旦客户端连接的数量超过了限制的最大值,就会导致客户端连接不上服务器。
  什么是NIO?
  先上代码为敬:publicclassNIOServer{publicstaticvoidmain(String〔〕args)throwsIOException{创建一个SelectorSelectorselectorSelector。open();创建一个ServerSocketChannel,并将其绑定到本地地址8888上ServerSocketChannelserverSocketChannelServerSocketChannel。open();serverSocketChannel。socket()。bind(newInetSocketAddress(8888));serverSocketChannel。configureBlocking(false);将ServerSocketChannel注册到Selector中,并指定需要监听OPACCEPT事件serverSocketChannel。register(selector,SelectionKey。OPACCEPT);while(true){阻塞直到有事件发生selector。select();获取所有SelectionKeyIteratorSelectionKeyiteratorselector。selectedKeys()。iterator();处理每一个SelectionKeywhile(iterator。hasNext()){SelectionKeykeyiterator。next();iterator。remove();如果SelectionKey是OPACCEPT,则处理新的连接if(key。isAcceptable()){ServerSocketChannelserver(ServerSocketChannel)key。channel();非阻塞SocketChannelclientserver。accept();System。out。println(Acceptedconnectionfromclient);client。configureBlocking(false);client。register(selector,SelectionKey。OPREAD);如果SelectionKey是OPREAD,则读取数据}elseif(key。isReadable()){SocketChannelclient(SocketChannel)key。channel();ByteBufferbufferByteBuffer。allocate(1024);client。read(buffer);buffer。flip();byte〔〕bytesnewbyte〔buffer。remaining()〕;buffer。get(bytes);System。out。println(Receivedmessage:newString(bytes));返回响应给客户端ByteBufferresponseBufferByteBuffer。wrap(Hello,client!。getBytes());client。write(responseBuffer);}}}}}
  代码虽长,却非常简单。
  NIO只需要关注三个东西:
  1。Channel:可以理解为BIO中的Socket通道,只不过BIO的Socket是单向的,这个是双向的,可以同时读写。
  2。Selector:选择器。把那些活跃的Channel(想要链接服务端的Channel,需要读写数据的Channel)挑出来,供后续的处理。
  3。SelectionKey:标记Channel想要进行什么操作,比如连接操作,读写操作。处理Channel的时候会根据Key来进行相应的操作。
  代码的大致原理如下图:
  比如客户端连接服务器,可能会经过如下步骤:
  1。客户端A要连接服务器,服务器接收到之后就会打开一个ServerSocketChannel
  2。然后就会把这个ServerSocketChannel(可以理解为BIO中的ServerSocket)注册到Selector(也就是交给Selector管理这个Channel),并绑定一个OPACCEPT(代表Channel需要进行连接)事件
  3。然后会有一个循环,不断的从Selector获取活跃的Key并进行处理
  4。一旦发现了OPACCEPT,就会创建一个SocketChannel(相当于BIO中的Socket),此时一个连接通道就建立完成了
  5。然后会把这个SocketChannel注册到Selector中,并绑定一个OPREAD事件
  6。如果客户端A发送了一个数据,那么Selector就会监控到这个动作,下一次循环的时候就会从Selector中取出活跃的Channel,并根据对应的OPREAD事件进行处理。
  这就是NIO处理连接的大体流程。
  可能有人会有疑问。这哪里变成非阻塞了?
  对照BIO。NIO的非阻塞就是上面说的那两个:
  1。服务端不会阻塞的等待客户端链接,即server。accept()不会阻塞。
  2。数据没有准备好的时候,读写不会阻塞。即NIO不会存在像BIO那样有线程什么也不干,白白楞在那。
  之所以不会阻塞,是因为在NIO中一个线程会处理多个连接。并且处理的都是Selector过滤之后的活跃连接(有accept或者读写操作的连接),所以不存在线程啥也不干,空等的阻塞现象。
  这里的阻塞很多人其实没有理解明白,网上很多人其实自己都不理解,写出的文章更是难以自圆其说。
  为了行文流畅,这里先不花篇幅解释这个概念。下文会集中讲解。
  什么是Netty?
  因为NIO的API封装的并不好,业务端开发的时候会写很多的模板代码。所以Netty对NIO进行了再次的封装,并在NIO的基础上进行了一些优化。
  Netty就不做过多介绍了,只要理解了上面的NIO模型,Netty很容易理解。
  什么是AIO?
  该模型是异步非阻塞。你可以理解为在NIO中如果读一个数据,是自己的应用程序在处理这些数据。
  但是如果是AIO,就相当于在自己的程序中定义了一段逻辑,但是执行的时候是由操作系统直接执行的,和应用没有关系。
  也就是说如果发现IO读写是自己的程序进行读写,那就是同步。如果不是那就是异步。
  一个故事说明BIO,NIO,AIO
  比如一个餐馆。每个顾客就是一个客户端,每个服务员就是一个线程。
  在BIO模型下餐馆会给每个顾客配一个服务员,如果该顾客有需求,那么服务员就处理顾客的需求。如果顾客没有要求,那服务员就在旁边傻站着发呆。
  在NIO模型下餐馆会让一个服务员负责多个顾客。哪个顾客有需求,服务员就去服务那个顾客。如果收到一个需求就会一直处理,直到处理好返回给顾客。并且会经常问顾客们:还需不需要什么服务?。
  在AIO模型下一个服务员同样负责多个顾客。但是如果有多个顾客点了菜,那么服务员会写一个纸条(回调函数),纸条上写好客户的需求以及如何处理,然后交给一个神秘大佬(操作系统)。神秘大佬操作完成之后会通知服务员。相当于服务员把自己的活外包了。
  可以仔细体会下,NIO和AIO的区别就是IO的操作由谁来完成。如果由应用程序自己来完成,那就是传说中的同步IO,否则就是传说中的异步IO。
  究竟什么是多路复用?
  多路复用就是一个线程管理多个连接。路可以理解为一个个的Channel,多个客户端就有多个Channel。
  但是并不是每个Channel都是活跃的,所以经过Selector之后,会把活跃的Channel挑出来,并对这些活跃的Channel进行处理。
  这个一个线程过滤多个连接并处理多个连接的动作就是多路复用,即多个连接复用一个线程。
  select,poll,epoll和网络IO模型究竟是什么关系?
  select,poll,epoll是多路复用的Linux操作系统层面的实现(Selector的底层实现)。网上资料比较多,没有什么歧义,此处不展开。
  什么是阻塞?
  其实网络IO模型中的阻塞指的是线程的空等现象。
  就比如BIO中开启的线程,可能什么也不干,等着客户端发数据,这种情况就是阻塞。
  再比如BIO中服务端accept()空等客户端的连接,这种情况也是阻塞。
  那NIO中accept(),read(),write()有人说也是阻塞,因为这些操作执行过程中需要时间,看起来也阻塞了线程。
  但是注意这里线程是真正的在干活,在工作,所以这种情况不叫阻塞,而是叫同步。
  什么是异步和同步?
  就像上面所说,NIO中的accept(),read(),write()操作需要应用程序亲自进行数据的操作就叫同步。
  相反,如果在应用程序中遇到这种操作直接往下走,而把这些操作交给操作系统执行,执行完成后通知应用程序,那么这种就叫异步。
  总结一下,就是说应用程序自己花时间读写数据就叫同步,如果应用程序自己不花时间,而是把这种操作交给其他人(比如操作系统),那么就是异步。
  那你思考一个问题,如果一个线程遇到了读数据的操作,然后开了一个子线程处理这种操作。这种情况属于同步还是异步?
  这种情况属于业务线程模型是异步,但是IO模型是同步。其实你可以这么理解,把业务线程和IO当作两个层面的东西。
  在一个业务线程中如果遇到读写自己不操作,而交给另一个线程操作,这叫业务线程的异步。
  那么同样在IO模型层面,如果应用自己不操作,而交给操作系统,那么这就叫做IO异步。
  更简单的理解方式就是你就看read(),write(),accept()等方法在自己程序中调用的时候会不会直接返回,如果是,那就是异步,如果不是那就是同步。
  多路复用一定要非阻塞吗?
  是,多路复用是一个线程负责处理多个连接。如果是阻塞的,只要有一个连接把线程阻塞了。那这个线程就废了,其他连接也处理不了。
  BIO一定不能用吗?
  技术都有它的应用场景。如果并发量比较低,是可以用BIO的。
  在连接数比较小的情况下BIO模型因为没有多路复用遍历活跃连接的过程,并且每个连接独享线程。性能不一定比NIO差。
  Redis用的什么IO模型?
  Redis底层也是多路复用。经常听到的别人口中的Redis是单线程,但是还是非常快的原因就是Redis是用epoll实现的多路复用。
  正因为是多路复用,如果一个命令耗时太长就可能占用线程的时间过长。影响其他命令的执行。
  所以用Redis的时候一定要关注执行的命令时间复杂度如何。比如keys一般情况下公司是禁止执行的。
  小思考题:你能用一句话说明白什么才算是高性能吗?快发到评论区吧〔看〕

iPhone135月份总销量突破4000万台在华市场份额暴增根据苹果给投资者的一份新报告介绍,摩根大通分析师萨米克查特吉(SamikChatterji)指出,5月份iPhone的出货量超过了历史平均水平。查特吉报告称,5月份智能手机整体……华为再传好消息麒麟kc10浮出水面,性能实现大跨越大家好,我是朱事66,点击右上角关注,我将持续为大家带来【科技】和【手机】方面的资讯。愿大家天天开心,事事顺利!正如华为轮值董事长徐直军在接受媒体采访时表示:海思在……蔡振华代言人落网3天后!国手名记剑指两个大老虎,点名3大特征最近中国足坛在反腐方面的行动越来越激烈,在日前有很好的成效。比如像杜兆才等那些足协高层已经落网,除此之外因为中国体坛的反腐行动取得重大突破,让整个中国体坛开始重视这一方面的反腐……造车新势力交出去年成绩单,理想汽车2023年率先上岸?随着零跑汽车2022年财报出炉,蔚来汽车、理想汽车、小鹏汽车、零跑汽车等四家上市的造车新势力均交出了2022年的成绩单。2022年新能源市场热度不减,造车新势力的可持续发……难辞其咎!塞拉斯让火箭乱作一团!或成联盟首位被解雇主教练近日,NBA专家霍林格提出了一个大胆的预测,他认为火箭队塞拉斯将会成为本赛季第一位被解雇的主帅。在联盟中,优质主教练可遇不可求,波波维奇可以让一支年轻的马刺打得有声有色,……4月新能源SUV销量丨特斯拉落榜,比亚迪包揽前三,问界M5让日前,乘联会公布了4月最新的销量数据。新能源SUV方面,和市场大行情不同的是,大部分车型都迎来了销量大幅增长,当然主要原因还是因为此前基数较低。而另一方面,也反映出消费者消费观……5年2。3亿美元!继莫兰特后,NBA又一个年轻人拿到了超级合还不满23岁的莫兰特在今日和灰熊达成了最低5年1。93亿美元、最高5年2。31亿美元的提前续约合同,只要新赛季莫兰特达成3个条件中的1个(入选全明星首发或入选最佳阵容或拿到常规……滇行记2022(四十三)两颗带星的行程码,成了拦路虎自助煎个蛋住云蔓酒店最开心的事之一,就是可以享受早上的那顿自助餐。不仅性价比高,还兼具地方特色,每天早上我都要在这里消磨一个小时。今天计划去松赞林寺,再去白水台。松……家长警惕!性侵色情泛滥性无知等危险靠近孩子,你可以用这些方法废话不多说,直奔主题〔比心〕前年10月13日,一位加拿大华人小提琴老师因性侵被捕,让科大大震惊又气愤:这个老师不仅是国家一级演出家,还是中国音乐家协会成员,教学30……国产屏力压三星屏成厂商首选?网友小米这回玩真的对于屏幕这块三星一直都是有说法的,可以说不管是在电脑端亦或者是手机端三星屏都颇为吃香。不过为了打破三星对于屏幕方面的垄断,国产屏近几年也大有崛起之势,其中又以华星光电为首,根据……我已换绑北京健康宝手机号,为何还要用原号查询?详解来了近期,有网友反馈,出差返京后进行行程核验时,北京健康宝绑定过的两个手机号码都需要验证。由于其中一个号码已作废不再使用,导致无法进行核验,健康宝无法正常使用。需要特别注意的……球迷还原U15冲突金华队教练说到动情处跪下,球员也跟着跪下直播吧9月30日讯9月27日,浙江省运会足球U15乙组决赛,输球的金华队赛后追打裁判,运动员集体跪地,拒绝领奖。据记者徐毅报道,现场观赛的球迷还原了当时的情况,称组委会取消了颁……
热血传奇两把魔10的武器,一把吓人,一把低端!却败给海魂热血传奇中升级最多的武器就是战士职业的,其次是法师职业的,最后就是道士职业的。其实早年玩法师的玩家数量挺多的,只不过后来玩不下去了才逐渐数量减少的。因此法师武器也有不少升级出不……端着一张脸就别演警花了,这四位女演员告诉你,啥是飒爽长官气派去年开年正午阳光以一部扶贫剧《山海情》引爆了收视率;一年之后,它又以新题材时间循环短剧《开端》再次引发全网观剧潮。在《开端》中一众演员的演技可圈可点,赵今麦、白敬亭……王思聪打人事件后,带4位网红美女现身海南,住18万套房文栗子编辑世界前言王思聪可以说是富二代的代表,可是最近这个富二代,也学着一些劣迹明星走上了翻车路,甚至让自己带上了国家的银手镯。王校长这些年的行为,是如……出游必看!百岛新春两日游攻略,带你去个有山有水有风有烟花的地百岛新春两日游攻略叶子怡摄凛冬散尽,迎来2023的曙光与时光轻语,话岁月更迭百岛君倾情推荐百岛新春两日游攻略愿新的一年我们依然可以奔走……国民好物分享墙面扩展插孔好物,解决生活小问题如今家里各种用电的设备那是越来越多了,随之而来的问题就是插座也越来越不够用,往往需要用一台电器的时候,就得必须拔下另一个,每次都这样实在是折腾。近日,为了解决厨房电器和孩子桌旁……给前妻11。5亿赡养费,离开18年结发妻子,和小16岁的美女择一城终老,携一人白首。这是很多人的梦想。但是人生中有许多人,走着走着就散了,连回忆都淡了;看着看着就累了,星光也暗了;听着听着就厌了,开始埋怨了,回头发现你不见了,突然我乱了……有种偏心叫做佟大为的俩女儿,13岁身高超过妈妈,腿长不输关晓佟大为一家四口近期爆出合照,大女儿的身高是亮点,13岁身高比妈妈还高,腿长不比输关晓彤,不过不都说俩姐妹应该是长得比较像吗?毕竟基因都是相同的,佟大为的这俩个女儿相比之下还是很……早上金苹果,晚上毒苹果?一日一苹果,医生远离我?关于苹果的真我们都知道吃苹果对身体好。有一句顺口溜,相信很多人都听过,一日一苹果,医生远离我,然而真的有科学根据吗?还有一种说法是早上金苹果,中午银苹果,晚上毒苹果,到底真相是……再见了!NBA榜眼霍姆格伦目前,NBA交易市场正在火热进行中,联赛各队都在积极备战这场没有硝烟的抢人大战,力争帮助球队在今夏完成阵容的升级补强,以在新赛季拿到更多场次的胜利,吸睛无数。与此同时,交易市场……04,莫拉塔2球勒马尔轰入超远任意球,尤文完败,西蒙尼4战全意甲豪门老妇人尤文图斯迎来了季前友谊赛的第4场较量,他们此役的对手是西甲劲旅马德里竞技队。在此前已经打完的3场友谊赛,尤文仅在第一场战胜了瓜达拉哈拉队,随后战平了巴萨,上……美兔秀秀济南的天鹅湖,天鹅在这里翩翩起舞这个冬季,济南鹊山水库沉砂池迎来不少大天鹅在此栖息越冬。1月28日,农历大年初七,这些来自远方的美丽精灵或展翅飞翔,或悠闲游弋,或翩翩起舞,或随意而眠,为冬日的黄河增添了诗情画……蔡澜人不强留,事不强求人活一世,怎样才算活得通透?我想大概是明白这八个字:人不强留,事不强求。很多事情没你想得那么难,也没你想得那么简单,如果你学会保持定力,从容面对,很多风雨都可以轻松……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网