bio nio aio区别_8分钟深入浅出搞懂BIO、NIO、AIO
在高性能的IO體系設(shè)計(jì)中,BIO、NIO、AIO的概念,常常會(huì)讓我們感到困惑不解。在Java面試中,我們也經(jīng)常會(huì)被問到這個(gè)問題。譬如:
- BIO、NIO、AIO 的概念
- 同步/異步、阻塞/非阻塞的區(qū)別
- NIO 如何實(shí)現(xiàn)多路復(fù)用功能
- AIO、BIO、NIO的適用場景
- NIO的核心概念、應(yīng)用和框架等等
這塊內(nèi)容本身比較復(fù)雜,很難用三言兩語說明白,而書上的定義不太容易理解。本篇內(nèi)容按照我的理解,以盡可能簡單、易懂的語言進(jìn)行組織,希望能夠幫助到大家快速理解這些概念。
AIO、BIO、NIO的區(qū)別
在弄清楚上面的幾個(gè)問題之前,我們首先得明白什么是同步,異步,阻塞,非阻塞,只有這幾個(gè)單個(gè)概念理解清楚了,然后在組合理解起來,就相對(duì)比較容易了。
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)會(huì)通知對(duì)應(yīng)的線程來處理。對(duì)應(yīng)到燒開水中就是,為每個(gè)水壺上面裝了一個(gè)開關(guān),水燒開之后,水壺會(huì)自動(dòng)通知我水燒開了。
http://4.IO與NIO區(qū)別
5.同步與異步的區(qū)別
- 同步
發(fā)送一個(gè)請(qǐng)求,等待返回,再發(fā)送下一個(gè)請(qǐng)求,同步可以避免出現(xiàn)死鎖,臟讀的發(fā)生。
- 異步
發(fā)送一個(gè)請(qǐng)求,不等待返回,隨時(shí)可以再發(fā)送下一個(gè)請(qǐng)求,可以提高效率,保證并發(fā)。
6.阻塞和非阻塞
- 阻塞
傳統(tǒng)的IO流都是阻塞式的。也就是說,當(dāng)一個(gè)線程調(diào)用read()或者write()方法時(shí),該線程將被阻塞,直到有一些數(shù)據(jù)讀讀取或者被寫入,在此期間,該線程不能執(zhí)行其他任何任務(wù)。在完成網(wǎng)絡(luò)通信進(jìn)行IO操作時(shí),由于線程會(huì)阻塞,所以服務(wù)器端必須為每個(gè)客戶端都提供一個(gè)獨(dú)立的線程進(jìn)行處理,當(dāng)服務(wù)器端需要處理大量的客戶端時(shí),性能急劇下降。
- 非阻塞
JavaNIO是非阻塞式的。當(dāng)線程從某通道進(jìn)行讀寫數(shù)據(jù)時(shí),若沒有數(shù)據(jù)可用時(shí),該線程會(huì)去執(zhí)行其他任務(wù)。線程通常將非阻塞IO的空閑時(shí)間用于在其他通道上執(zhí)行IO操作,所以單獨(dú)的線程可以管理多個(gè)輸入和輸出通道。因此NIO可以讓服務(wù)器端使用一個(gè)或有限幾個(gè)線程來同時(shí)處理連接到服務(wù)器端的所有客戶端。
7.BIO、NIO、AIO適用場景
- BIO方式適用于連接數(shù)目比較小且固定的架構(gòu),這種方式對(duì)服務(wù)器資源要求比較高,并發(fā)局限于應(yīng)用中,JDK1.4以前的唯一選擇。
- NIO方式適用于連接數(shù)目多且連接比較短(輕操作)的架構(gòu),比如聊天服務(wù)器,并發(fā)局限于應(yīng)用中,編程比較復(fù)雜。
- AIO方式使用于連接數(shù)目多且連接比較長(重操作)的架構(gòu),比如相冊(cè)服務(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è)對(duì)象。它包含一些要寫入或者讀出的數(shù)據(jù)。在面向流的I/O中,可以將數(shù)據(jù)寫入或者將數(shù)據(jù)直接讀到Stream對(duì)象中。
在NIO中,所有的數(shù)據(jù)都是用緩沖區(qū)處理。這也就本文上面談到的IO是面向流的,NIO是面向緩沖區(qū)的。
緩沖區(qū)實(shí)質(zhì)是一個(gè)數(shù)組,通常它是一個(gè)字節(jié)數(shù)組(ByteBuffer),也可以使用其他類的數(shù)組。但是一個(gè)緩沖區(qū)不僅僅是一個(gè)數(shù)組,緩沖區(qū)提供了對(duì)數(shù)據(jù)的結(jié)構(gòu)化訪問以及維護(hù)讀寫位置(limit)等信息。
最常用的緩沖區(qū)是ByteBuffer,一個(gè)ByteBuffer提供了一組功能于操作byte數(shù)組。除了ByteBuffer,還有其他的一些緩沖區(qū),事實(shí)上,每一種Java基本類型(除了Boolean)都對(duì)應(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è)方向移動(dòng),而且通道可以用于讀,寫或者同時(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è)連接都會(huì)有一個(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只能管理非阻塞的通道,FileChannel是阻塞的,無法管理。
關(guān)鍵對(duì)象
- Selector:選擇器對(duì)象,通道注冊(cè)、通道監(jiān)聽對(duì)象和Selector相關(guān)。
- SelectorKey:通道監(jiān)聽關(guān)鍵字,通過它來監(jiān)聽通道狀態(tài)。
監(jiān)聽注冊(cè)
監(jiān)聽注冊(cè)在Selector
socketChannel.register(selector, SelectionKey.OP_READ);監(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ū)動(dòng)的網(wǎng)絡(luò)應(yīng)用程序框架和工具,用以快速開發(fā)高性能、高可靠性的網(wǎng)絡(luò)服務(wù)器和客戶端程序。
相比JDK原生NIO,Netty提供了相對(duì)十分簡單易用的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)勢:
Netty無疑是NIO框架的首選,它的健壯性、功能、性能、可定制性和可擴(kuò)展性在同類框架都是首屈一指的,后續(xù)將重點(diǎn)詳細(xì)談Netty的實(shí)現(xiàn)原理以及實(shí)戰(zhàn)場景。
以上,是關(guān)于BIO、NIO、AIO的知識(shí)點(diǎn)梳理總結(jié)。
如果覺得有用,請(qǐng)點(diǎn)贊支持下~
更多免費(fèi)的BAT架構(gòu)技術(shù)干貨連載分享,進(jìn)入專欄了解:【直通BAT】進(jìn)階Java架構(gòu)師
------end------
高贊文章推薦:
阿里Java研發(fā):4大核心事業(yè)部面試題116送答案(2019年最新整理)
MySQL高頻面試60題含答案
Redis哨兵、復(fù)制、集群的設(shè)計(jì)原理與區(qū)別
Redis緩存和MySQL數(shù)據(jù)一致性方案詳解
如何解決Redis雪崩、穿透、并發(fā)等5大難題
Redis并發(fā)競爭key的解決方案詳解
Redis為什么是單線程,高并發(fā)快的3大原因詳解
Redis面試題目49道附答案
總結(jié)
以上是生活随笔為你收集整理的bio nio aio区别_8分钟深入浅出搞懂BIO、NIO、AIO的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux配置ip地址 suse_sus
- 下一篇: 字典树实现_学习NLP的第3天——字典树