AIO李皇、BIO、NIO的區(qū)別
IO模型主要分類:
- 同步(synchronous) IO和異步(asynchronous) IO
- 阻塞(blocking) IO和非阻塞(non-blocking)IO
- 同步阻塞(blocking-IO)簡稱BIO
- 同步非阻塞(non-blocking-IO)簡稱NIO
- 異步非阻塞(synchronous-non-blocking-IO)簡稱AIO
1.BIO (同步阻塞I/O模式)
數(shù)據(jù)的讀取寫入必須阻塞在一個(gè)線程內(nèi)等待其完成宙枷。
這里使用那個(gè)經(jīng)典的燒開水例子掉房,這里假設(shè)一個(gè)燒開水的場景卓囚,有一排水壺在燒開水诅病,BIO的工作模式就是贤笆, 叫一個(gè)線程停留在一個(gè)水壺那芥永,直到這個(gè)水壺?zé)_埋涧,才去處理下一個(gè)水壺棘催。但是實(shí)際上線程在等待水壺?zé)_的時(shí)間段什么都沒有做醇坝。
2.NIO(同步非阻塞)
同時(shí)支持阻塞與非阻塞模式,但這里我們以其同步非阻塞I/O模式來說明呀袱,那么什么叫做同步非阻塞夜赵?如果還拿燒開水來說乡革,NIO的做法是叫一個(gè)線程不斷的輪詢每個(gè)水壺的狀態(tài)摊腋,看看是否有水壺的狀態(tài)發(fā)生了改變兴蒸,從而進(jìn)行下一步的操作细办。
3.AIO (異步非阻塞I/O模型)
異步非阻塞與同步非阻塞的區(qū)別在哪里?異步非阻塞無需一個(gè)線程去輪詢所有IO操作的狀態(tài)改變岛啸,在相應(yīng)的狀態(tài)改變后坚踩,系統(tǒng)會通知對應(yīng)的線程來處理瞬铸。對應(yīng)到燒開水中就是,為每個(gè)水壺上面裝了一個(gè)開關(guān)拦宣,水燒開之后恢着,水壺會自動通知我水燒開了。
4.IO與NIO區(qū)別:
5.同步與異步的區(qū)別:
同步:發(fā)送一個(gè)請求左痢,等待返回系洛,再發(fā)送下一個(gè)請求俊性,同步可以避免出現(xiàn)死鎖,臟讀的發(fā)生定页。
異步:發(fā)送一個(gè)請求,不等待返回典徊,隨時(shí)可以再發(fā)送下一個(gè)請求杭煎,可以提高效率卒落,保證并發(fā)羡铲。
6.阻塞和非阻塞
阻塞:傳統(tǒng)的IO流都是阻塞式的。也就是說儡毕,當(dāng)一個(gè)線程調(diào)用read()或者write()方法時(shí),該線程將被阻塞腰湾,直到有一些數(shù)據(jù)讀讀取或者被寫入檐盟,在此期間,該線程不能執(zhí)行其他任何任務(wù)羡忘。在完成網(wǎng)絡(luò)通信進(jìn)行IO操作時(shí)谎痢,由于線程會阻塞,所以服務(wù)器端必須為每個(gè)客戶端都提供一個(gè)獨(dú)立的線程進(jìn)行處理漫雕,當(dāng)服務(wù)器端需要處理大量的客戶端時(shí)滨嘱,性能急劇下降。
非阻塞:Java
NIO是非阻塞式的浸间。當(dāng)線程從某通道進(jìn)行讀寫數(shù)據(jù)時(shí)太雨,若沒有數(shù)據(jù)可用時(shí),該線程會去執(zhí)行其他任務(wù)魁蒜。線程通常將非阻塞IO的空閑時(shí)間用于在其他通道上執(zhí)行IO操作囊扳,所以單獨(dú)的線程可以管理多個(gè)輸入和輸出通道。因此NIO可以讓服務(wù)器端使用一個(gè)或有限幾個(gè)線程來同時(shí)處理連接到服務(wù)器端的所有客戶端兜看。
7.BIO锥咸、NIO、AIO適用場景
- BIO方式適用于連接數(shù)目比較小且固定的架構(gòu)细移,這種方式對服務(wù)器資源要求比較高搏予,并發(fā)局限于應(yīng)用中,JDK1.4以前的唯一選擇弧轧。
- NIO方式適用于連接數(shù)目多且連接比較短(輕操作)的架構(gòu)雪侥,比如聊天服務(wù)器球涛,并發(fā)局限于應(yīng)用中,編程比較復(fù)雜校镐。
- AIO方式使用于連接數(shù)目多且連接比較長(重操作)的架構(gòu)亿扁,比如相冊服務(wù)器,充分調(diào)用OS參與并發(fā)操作鸟廓,編程比較復(fù)雜从祝,JDK7開始支持。
NIO的3個(gè)核心概念
NIO重點(diǎn)是把Channel(通道)引谜,Buffer(緩沖區(qū))牍陌,Selector(選擇器)三個(gè)類之間的關(guān)系弄清楚。
1.緩沖區(qū)Buffer
Buffer是一個(gè)對象员咽。它包含一些要寫入或者讀出的數(shù)據(jù)毒涧。在面向流的I/O中,可以將數(shù)據(jù)寫入或者將數(shù)據(jù)直接讀到Stream對象中贝室。
在NIO中契讲,所有的數(shù)據(jù)都是用緩沖區(qū)處理。這也就本文上面談到的IO是面向流的滑频,NIO是面向緩沖區(qū)的捡偏。
緩沖區(qū)實(shí)質(zhì)是一個(gè)數(shù)組,通常它是一個(gè)字節(jié)數(shù)組(ByteBuffer)峡迷,也可以使用其他類的數(shù)組银伟。但是一個(gè)緩沖區(qū)不僅僅是一個(gè)數(shù)組,緩沖區(qū)提供了對數(shù)據(jù)的結(jié)構(gòu)化訪問以及維護(hù)讀寫位置(limit)等信息绘搞。
最常用的緩沖區(qū)是ByteBuffer彤避,一個(gè)ByteBuffer提供了一組功能于操作byte數(shù)組。除了ByteBuffer夯辖,還有其他的一些緩沖區(qū)琉预,事實(shí)上,每一種Java基本類型(除了Boolean)都對應(yīng)一種緩沖區(qū)楼雹,具體如下:
- ByteBuffer:字節(jié)緩沖區(qū)
- CharBuffer:字符緩沖區(qū)
- ShortBuffer:短整型緩沖區(qū)
- IntBuffer:整型緩沖區(qū)
- LongBuffer:長整型緩沖區(qū)
- FloatBuffer:浮點(diǎn)型緩沖區(qū)
- DoubleBuffer:雙精度浮點(diǎn)型緩沖區(qū)
2.通道Channel
Channel是一個(gè)通道模孩,可以通過它讀取和寫入數(shù)據(jù)尖阔,他就像自來水管一樣贮缅,網(wǎng)絡(luò)數(shù)據(jù)通過Channel讀取和寫入。
通道和流不同之處在于通道是雙向的介却,流只是在一個(gè)方向移動谴供,而且通道可以用于讀,寫或者同時(shí)用于讀寫齿坷。
因?yàn)镃hannel是全雙工的桂肌,所以它比流更好地映射底層操作系統(tǒng)的API数焊,特別是在UNIX網(wǎng)絡(luò)編程中,底層操作系統(tǒng)的通道都是全雙工的崎场,同時(shí)支持讀和寫佩耳。
Channel有四種實(shí)現(xiàn):
- FileChannel:是從文件中讀取數(shù)據(jù)。
- DatagramChannel:從UDP網(wǎng)絡(luò)中讀取或者寫入數(shù)據(jù)谭跨。
- SocketChannel:從TCP網(wǎng)絡(luò)中讀取或者寫入數(shù)據(jù)干厚。
- ServerSocketChannel:允許你監(jiān)聽來自TCP的連接,就像服務(wù)器一樣螃宙。每一個(gè)連接都會有一個(gè)SocketChannel產(chǎn)生蛮瞄。
3.多路復(fù)用器Selector
Selector選擇器可以監(jiān)聽多個(gè)Channel通道感興趣的事情(read、write谆扎、accept(服務(wù)端接收)挂捅、connect,實(shí)現(xiàn)一個(gè)線程管理多個(gè)Channel堂湖,節(jié)省線程切換上下文的資源消耗闲先。Selector只能管理非阻塞的通道,F(xiàn)ileChannel是阻塞的无蜂,無法管理饵蒂。
關(guān)鍵對象
- Selector:選擇器對象,通道注冊酱讶、通道監(jiān)聽對象和Selector相關(guān)退盯。
- SelectorKey:通道監(jiān)聽關(guān)鍵字,通過它來監(jiān)聽通道狀態(tài)泻肯。
監(jiān)聽注冊
監(jiān)聽注冊在Selector
監(jiān)聽的事件有
- OP_ACCEPT: 接收就緒渊迁,serviceSocketChannel使用的
- OP_READ: 讀取就緒,socketChannel使用
- OP_WRITE: 寫入就緒灶挟,socketChannel使用
- OP_CONNECT: 連接就緒琉朽,socketChannel使用
NIO的應(yīng)用和框架
1.NIO的應(yīng)用
Java NIO成功的應(yīng)用在了各種分布式、即時(shí)通信和中間件Java系統(tǒng)中稚铣,充分的證明了基于NIO構(gòu)建的通信基礎(chǔ)箱叁,是一種高效,且擴(kuò)展性很強(qiáng)的通信架構(gòu)惕医。
例如:Dubbo(服務(wù)框架)耕漱,就默認(rèn)使用Netty作為基礎(chǔ)通信組件,用于實(shí)現(xiàn)各進(jìn)程節(jié)點(diǎn)之間的內(nèi)部通信抬伺。
Jetty螟够、Mina、Netty、Dubbo妓笙、ZooKeeper等都是基于NIO方式實(shí)現(xiàn)若河。
- Mina出身于開源界的大牛Apache組織
- Netty出身于商業(yè)開源大亨Jboss
- Dubbo阿里分布式服務(wù)框架
2.NIO框架
特別是Netty是目前最流行的一個(gè)Java開源框架NIO框架,Netty提供異步的寞宫、事件驅(qū)動的網(wǎng)絡(luò)應(yīng)用程序框架和工具萧福,用以快速開發(fā)高性能、高可靠性的網(wǎng)絡(luò)服務(wù)器和客戶端程序辈赋。
相比JDK原生NIO统锤,Netty提供了相對十分簡單易用的API,非常適合網(wǎng)絡(luò)編程炭庙。
Mina和Netty這兩個(gè)NIO框架的創(chuàng)作者是同一個(gè)人Trustin Lee 饲窿。Netty從某種程度上講是Mina的延伸和擴(kuò)展,解決了一些Mina上的設(shè)計(jì)缺陷焕蹄,也優(yōu)化了一下Mina上面的設(shè)計(jì)理念逾雄。
另一方面Netty相比較Mina的優(yōu)勢:
- 更容易學(xué)習(xí)
- API更簡單
- 詳細(xì)的范例源碼和API文檔
- 更活躍的論壇和社區(qū)
- 更高的代碼更新維護(hù)速度
Netty無疑是NIO框架的首選,它的健壯性腻脏、功能鸦泳、性能、可定制性和可擴(kuò)展性在同類框架都是首屈一指的永品,后續(xù)將重點(diǎn)詳細(xì)談Netty的實(shí)現(xiàn)原理以及實(shí)戰(zhàn)場景做鹰。
本文由博客一文多發(fā)平臺 OpenWrite 發(fā)布!