1.BIO、NIO和AIO概念
BIO:同步并阻塞卦洽,服務(wù)器的實(shí)現(xiàn)模式是一個(gè)連接一個(gè)線程替蛉,這樣的模式很明顯的一個(gè)缺陷是:由于客戶端連接數(shù)與服務(wù)器線程數(shù)成正比關(guān)系,可能造成不必要的線程開銷冠胯,嚴(yán)重的還將導(dǎo)致服務(wù)器內(nèi)存溢出火诸。當(dāng)然,這種情況可以通過線程池機(jī)制改善荠察,但并不能從本質(zhì)上消除這個(gè)弊端置蜀。
NIO:在JDK1.4以前,Java的IO模型一直是BIO悉盆,但從JDK1.4開始盯荤,JDK引入的新的IO模型NIO,它是同步非阻塞的焕盟。而服務(wù)器的實(shí)現(xiàn)模式是多個(gè)請(qǐng)求一個(gè)線程秋秤,即請(qǐng)求會(huì)注冊(cè)到多路復(fù)用器Selector上,多路復(fù)用器輪詢到連接有IO請(qǐng)求時(shí)才啟動(dòng)一個(gè)線程處理脚翘。
AIO:JDK1.7發(fā)布了NIO2.0灼卢,這就是真正意義上的異步非阻塞,服務(wù)器的實(shí)現(xiàn)模式為多個(gè)有效請(qǐng)求一個(gè)線程来农,客戶端的IO請(qǐng)求都是由OS先完成再通知服務(wù)器應(yīng)用去啟動(dòng)線程處理(回調(diào))鞋真。
2.NIO和IO的主要區(qū)別
- 面向流與面向緩沖
Java IO和NIO之間第一個(gè)最大的區(qū)別是,IO是面向流的沃于,NIO是面向緩沖區(qū)的涩咖。 Java IO面向流意味著每次從流中讀一個(gè)或多個(gè)字節(jié),直至讀取所有字節(jié)繁莹,它們沒有被緩存在任何地方檩互。此外,它不能前后移動(dòng)流中的數(shù)據(jù)蒋困。如果需要前后移動(dòng)從流中讀取的數(shù)據(jù)盾似,需要先將它緩存到一個(gè)緩沖區(qū)。 Java NIO的緩沖導(dǎo)向方法略有不同。數(shù)據(jù)讀取到一個(gè)它稍后處理的緩沖區(qū)零院,需要時(shí)可在緩沖區(qū)中前后移動(dòng)溉跃。這就增加了處理過程中的靈活性。但是告抄,還需要檢查是否該緩沖區(qū)中包含所有您需要處理的數(shù)據(jù)撰茎。而且,需確保當(dāng)更多的數(shù)據(jù)讀入緩沖區(qū)時(shí)打洼,不要覆蓋緩沖區(qū)里尚未處理的數(shù)據(jù)龄糊。 - 阻塞與非阻塞IO
Java IO的各種流是阻塞的。這意味著募疮,當(dāng)一個(gè)線程調(diào)用read() 或 write()時(shí)炫惩,該線程被阻塞,直到有一些數(shù)據(jù)被讀取阿浓,或數(shù)據(jù)完全寫入他嚷。該線程在此期間不能再干任何事情了。Java NIO的非阻塞模式芭毙,使一個(gè)線程從某通道發(fā)送請(qǐng)求讀取數(shù)據(jù)筋蓖,但是它僅能得到目前可用的數(shù)據(jù),如果目前沒有數(shù)據(jù)可用時(shí)退敦,就什么都不會(huì)獲取粘咖,而不是保持線程阻塞,所以直至數(shù)據(jù)變的可以讀取之前侈百,該線程可以繼續(xù)做其他的事情瓮下。 非阻塞寫也是如此。一個(gè)線程請(qǐng)求寫入一些數(shù)據(jù)到某通道钝域,但不需要等待它完全寫入唱捣,這個(gè)線程同時(shí)可以去做別的事情。 線程通常將非阻塞IO的空閑時(shí)間用于在其它通道上執(zhí)行IO操作网梢,所以一個(gè)單獨(dú)的線程現(xiàn)在可以管理多個(gè)輸入和輸出通道(channel)。 - 選擇器(Selectors)
Java NIO的選擇器允許一個(gè)單獨(dú)的線程來監(jiān)視多個(gè)輸入通道赂毯,你可以注冊(cè)多個(gè)通道使用一個(gè)選擇器战虏,然后使用一個(gè)單獨(dú)的線程來“選擇”通道:這些通道里已經(jīng)有可以處理的輸入,或者選擇已準(zhǔn)備寫入的通道党涕。這種選擇機(jī)制烦感,使得一個(gè)單獨(dú)的線程很容易來管理多個(gè)通道。
NIO提供了與標(biāo)準(zhǔn)IO不同的IO工作方式:
Channels and Buffers(通道和緩沖區(qū)):標(biāo)準(zhǔn)的IO基于字節(jié)流和字符流進(jìn)行操作的膛堤,而NIO是基于通道(Channel)和緩沖區(qū)(Buffer)進(jìn)行操作手趣,數(shù)據(jù)總是從通道讀取到緩沖區(qū)中,或者從緩沖區(qū)寫入到通道中。
Asynchronous IO(異步IO):Java NIO可以讓你異步的使用IO绿渣,例如:當(dāng)線程從通道讀取數(shù)據(jù)到緩沖區(qū)時(shí)朝群,線程還是可以進(jìn)行其他事情。當(dāng)數(shù)據(jù)被寫入到緩沖區(qū)時(shí)中符,線程可以繼續(xù)處理它姜胖。從緩沖區(qū)寫入通道也類似。
Selectors(選擇器):Java NIO引入了選擇器的概念淀散,選擇器用于監(jiān)聽多個(gè)通道的事件(比如:連接打開右莱,數(shù)據(jù)到達(dá))。因此档插,單個(gè)的線程可以監(jiān)聽多個(gè)數(shù)據(jù)通道慢蜓。
3.NIO的核心組件
Channel buffer selector
Channel和流有點(diǎn)類似。通過Channel郭膛,我們即可以從Channel把數(shù)據(jù)寫到Buffer中晨抡,也可以把數(shù)據(jù)沖Buffer寫入到Channel,每個(gè)channel對(duì)應(yīng)一個(gè)buffer緩沖區(qū)饲鄙,channel會(huì)注冊(cè)到selector凄诞。selector根據(jù)channel上發(fā)生的讀寫事件,將請(qǐng)求交由某個(gè)空閑的線程處理忍级,selector對(duì)應(yīng)一個(gè)或多個(gè)線程帆谍,channnel和buffer是可讀可寫的。
4.select轴咱、poll和epoll什么區(qū)別
他們是NIO多路復(fù)用的三種實(shí)現(xiàn)機(jī)制汛蝙,是有l(wèi)unix系統(tǒng)提供。
-select:無差別輪詢所有流朴肺,找出能讀出數(shù)據(jù)窖剑,或者寫入數(shù)據(jù)的流,對(duì)他們進(jìn)行操作戈稿,會(huì)維護(hù)一個(gè)文件描述符FD的集合fd_set西土,將fd_set從用戶空間復(fù)制到內(nèi)核空間。x86 fd_set是數(shù)組結(jié)構(gòu)
-poll:與select機(jī)制相似鞍盗,fd_set結(jié)構(gòu)進(jìn)行優(yōu)化需了,突破操作系統(tǒng)限制,pollfd代替fd_set般甲,鏈表結(jié)構(gòu)
-epoll:不再掃描所以fd肋乍,只將用戶關(guān)心的事件放在內(nèi)核的一個(gè)事件表中,減少用戶空間和內(nèi)核空間的數(shù)據(jù)拷貝敷存。epoll可以理解為event poll墓造,不同于忙輪詢和無差別輪詢,epoll會(huì)把哪個(gè)流發(fā)生了怎樣的I/O事件通知我們。