阿根廷都奪冠了,你還傻傻分不清BIO、NIO、AIO?

YYDS
我們知道java的I/O模型一共有四種,分別是:傳統(tǒng)的BIO,偽異步I/O,NIO和AIO。
為了澄清概念和分清區(qū)別,我們還是先簡(jiǎn)單的介紹一下他們的概念,然后再去比較優(yōu)劣。
1.概念澄清
1.1 BIO
BIO,即Blocking I/O。
網(wǎng)絡(luò)編程的基本模型是Client/Server 模型,也就是兩個(gè)進(jìn)程之間進(jìn)行相互通信,其中服務(wù)端提供位置信息(綁定的Ip 地址和監(jiān)聽(tīng)端口) ,客戶端通過(guò)連接操作向服務(wù)端監(jiān)聽(tīng)的地址發(fā)起連接請(qǐng)求,通過(guò)三次握手建立連接,如果連接建在成功,雙方就可以通過(guò)網(wǎng)絡(luò)套接字( Socket ) 進(jìn)行通信。
在基于傳統(tǒng)同步阻塞模型開(kāi)發(fā)中, ServerSocket 負(fù)責(zé)綁定IP 地址,啟動(dòng)監(jiān)聽(tīng)端口:Socket 負(fù)責(zé)發(fā)起連接操作。連接成功之后,雙方通過(guò)輸入和輸出流進(jìn)行同步阻塞式通信。
BIO通信模型圖:

解釋一下上圖:
1.2 偽異步IO
為了解決同步阻塞 I/O 面臨的一個(gè)鏈路需要一個(gè)線程處理的問(wèn)題,后來(lái)有人對(duì)它的線程模型進(jìn)行了優(yōu)化一一后端通過(guò)一個(gè)線程池來(lái)處理多個(gè)客戶端的請(qǐng)求接入,形成客戶端個(gè)數(shù)M: 線程池最大線程數(shù)N 的比例關(guān)系,其中M 可以遠(yuǎn)遠(yuǎn)大于N。通過(guò)線程地可以靈活地調(diào)配線程資源,設(shè)置線程的最大值,防止由于海量并發(fā)接入導(dǎo)致線程耗盡。
偽異步IO通信模型圖:

由于統(tǒng)程池可以設(shè)置消息隊(duì)列的大小和最大線程數(shù),因此,它的資源占用是可控的, 無(wú)論多少個(gè)客戶端并發(fā)訪問(wèn), 都不會(huì)導(dǎo)致資源的耗盡和省機(jī)。更多 Java 教程和示例代碼:https://github.com/javastacks/javastack
服務(wù)端處理緩慢,返回應(yīng)答消息耗費(fèi)60s,平時(shí)只需要10ms; 采用偽異步I/O 的線程在讀取故障服務(wù)節(jié)點(diǎn)的響應(yīng),由于讀/取輸入流是阻塞的,它將會(huì)被同步阻塞60s; 假如所有的可用線程都被故障服務(wù)器阻塞,那后續(xù)的所有的I/O消息都將在隊(duì)列中排隊(duì); 由于線程地采用阻塞隊(duì)列實(shí)現(xiàn),當(dāng)隊(duì)列積滿之后,后續(xù)入隊(duì)列的操作將被阻塞; 由于前端只有一個(gè)Accptor 線程接收客戶端接入,它被阻塞在線程池的同步阻塞隊(duì)列之后,新的客戶端請(qǐng)求消息將被拒絕,客戶端會(huì)發(fā)生大量的連接超時(shí); 由于幾于所有的連接都超時(shí),調(diào)用者會(huì)認(rèn)為系統(tǒng)已經(jīng)崩潰,無(wú)法接收新的請(qǐng)求消息。
如何破解這個(gè)難題?下面我們?cè)倏匆幌翹IO。微信搜索Java技術(shù)棧,在后臺(tái)回復(fù):面試,可以獲取我整理的 Java/ IO 系列面試題和答案,非常齊全。
1.3 NIO
NIO,很多人叫他New I/O,由于之前老的I/O 類庫(kù)是阻塞I/O ,New I/O 類庫(kù)的目標(biāo)就是要讓Java 支持非阻塞I/O,所以,更多的人喜歡稱之為非阻塞I/O(Non-block I/O)。
與Socket類和ServerSocket 類相對(duì)應(yīng), NIO也提供了SocketChannel 和ServerSocketChannel兩種不同的套接字通道實(shí)現(xiàn)。這兩種新增的通道都支持阻塞和非阻塞兩種模式。阻塞模式使用非常簡(jiǎn)單,但是性能和可靠性都不好,非阻塞模式則正好相反。開(kāi)發(fā)人員可以根據(jù)自己的需要來(lái)選擇合適的模式。
一般來(lái)說(shuō),低負(fù)載、低并發(fā)的應(yīng)用程序可以選擇同步阻塞I/O以降低編程復(fù)雜度:對(duì)于高負(fù)載、高并發(fā)的網(wǎng)絡(luò)應(yīng)用,需要使用NIO 的非阻塞模式進(jìn)行開(kāi)發(fā)。Spring Boot 學(xué)習(xí)筆記,這個(gè)分享給你。
前面我們已經(jīng)對(duì)NIO進(jìn)行了介紹,我們知道NIO中引入了緩沖區(qū)Buffer,通道Channel和多路復(fù)用器Selector的概念。一個(gè)多路復(fù)用器Selector 可以同時(shí)輪詢多個(gè)Channel,而Channel又是全雙工的,同時(shí)支持讀寫(xiě)操作,使用NIO 編程的優(yōu)點(diǎn)總結(jié)如下:
客戶端發(fā)起的連接操作是異步的,可以通過(guò)在多路復(fù)用器注冊(cè)O(shè)P_CONNECT 等待后續(xù)結(jié)果,不需要像之前的客戶端那樣被同步阻塞。 SocketChannel 的讀寫(xiě)操作都是異步的,如果沒(méi)有可讀寫(xiě)的數(shù)據(jù)它不會(huì)同步等待,直接返回,這樣I/O 通信線程就可以處理其他的鏈路,不需要同步等待這個(gè)鏈路可用。 線程模型的優(yōu)化:由于JDK 的Selector 在Linux 等主流操作系統(tǒng)上通過(guò)epoll 實(shí)現(xiàn),它沒(méi)有連接句柄數(shù)的限制(只受限于操作系統(tǒng)的最大句柄數(shù)或者對(duì)單個(gè)進(jìn)程的句柄限制),這意味著一個(gè)Selector 線程可以同時(shí)處理成千上萬(wàn)個(gè)客戶端連接,而且性能不會(huì)隨著客戶端的增加而線性下降。因此,它非常適合做高性能、高負(fù)載的網(wǎng)絡(luò)服務(wù)器。
1.4 AIO
NIO 2.0 引入了新的異步通道的概念,并提供了異步文件通道和異步套接字通道的實(shí)現(xiàn)。
?通過(guò)java.util.concurrent.Future 類來(lái)表示異步操作的結(jié)果;
?在執(zhí)行異步操作的時(shí)候傳入一個(gè)java.nio.channels;
前面對(duì)不同的I/O模型進(jìn)行了簡(jiǎn)單介紹,不同的I/O 模型由于線程模型、API 等差別很大,所以用法的差異也非常大。
我們用一個(gè)表格來(lái)做一個(gè)統(tǒng)一說(shuō)明:

最后,關(guān)注公眾號(hào)Java技術(shù)棧,在后臺(tái)回復(fù):面試,可以獲取我整理的 Java/ IO 系列面試題和答案,非常齊全。
作者:rickiyang
出處:www.cnblogs.com/rickiyang/p/11074238.html
——————END——————
歡迎關(guān)注“Java引導(dǎo)者”,我們分享最有價(jià)值的Java的干貨文章,助力您成為有思想的Java開(kāi)發(fā)工程師!
