一遂唧、IO NIO AIO
io芙代、nio、aio的區(qū)別盖彭,類似于resin纹烹、apache、nginx在io處理上的區(qū)別召边,從多線程互不干擾的阻塞式執(zhí)行(resin)铺呵,到輪詢式的同步非阻塞式(apache),再到異步非阻塞式(nginx)掌实。
三種io都在jdk中予以了支持陪蜻。
- IO (BIO)
同步并阻塞邦马,服務(wù)器實(shí)現(xiàn)模式為一個連接一個線程贱鼻,每個線程親自處理io并且一直等待io的完成宴卖,即客戶端有連接請求時服務(wù)器端就需要啟動一個線程進(jìn)行處理,如果這個連接不做任何事情會造成不必要的線程開銷邻悬,當(dāng)然可以通過線程池機(jī)制改善症昏。
IO的局限:IO是面向流的,阻塞式的父丰,串行的一個過程肝谭。對每一個客戶端的socket連接,IO都需要一個線程來處理蛾扇,而且在此期間攘烛,這個線程一直被占用,直到socket關(guān)閉镀首。在這期間坟漱,tcp的連接、數(shù)據(jù)的讀取更哄、數(shù)據(jù)的返回都是被阻塞的芋齿。也就是說這期間大量的浪費(fèi)了cpu的時間片和線程占用的內(nèi)存資源。
每建立一個Socket連接時成翩,同時創(chuàng)建一個新線程對該Socket進(jìn)行單獨(dú)通信(采用阻塞的方式通信)觅捆。這種方式具有很高的響應(yīng)速度,并且控制起來也很簡單麻敌,在連接數(shù)較少的時候非常有效栅炒,但是如果對每一個連接都產(chǎn)生一個線程的無疑是對系統(tǒng)資源的一種浪費(fèi),如果連接數(shù)較多將會出現(xiàn)資源不足的情況庸论。 - NIO (new IO) 從jdk1.4開始
同步非阻塞职辅,服務(wù)器實(shí)現(xiàn)模式為一個請求一個線程,每個線程親自處理io聂示,但有另外的線程輪詢檢查是否io準(zhǔn)備完畢域携,不必等待io完成,即客戶端發(fā)送的連接請求都會注冊到多路復(fù)用器上鱼喉,多路復(fù)用器輪詢到連接有I/O請求時才啟動一個線程進(jìn)行處理秀鞭。
**NIO則是面向緩沖區(qū)的,非阻塞式的扛禽,基于選擇器的锋边,用一個線程來輪詢監(jiān)控多個數(shù)據(jù)傳輸通道,哪個通道準(zhǔn)備好了(即有了一組可以處理的數(shù)據(jù))编曼,就處理哪個通道豆巨。 **
服務(wù)器端保存一個Socket連接列表,然后對這個列表進(jìn)行輪詢掐场,如果發(fā)現(xiàn)某個Socket端口上有數(shù)據(jù)可讀時(讀就緒)往扔,則調(diào)用該socket連接的相應(yīng)讀操作贩猎;如果發(fā)現(xiàn)某個 Socket端口上有數(shù)據(jù)可寫時(寫就緒),則調(diào)用該socket連接的相應(yīng)寫操作萍膛;如果某個端口的Socket連接已經(jīng)中斷吭服,則調(diào)用相應(yīng)的析構(gòu)方法關(guān)閉 該端口。這樣能充分利用服務(wù)器資源蝗罗,效率得到了很大提高艇棕。 - AIO (Asynchronous io、NIO.2) 從jdk1.7開始
異步非阻塞串塑,服務(wù)器實(shí)現(xiàn)模式為一個有效請求一個線程沼琉,客戶端的I/O請求都是由OS先完成了再通知服務(wù)器應(yīng)用去啟動線程進(jìn)行處理,每個線程不必親自處理io桩匪,而是委派os來處理刺桃,并且也不需要等待io完成了,如果完成后吸祟,os會通知的瑟慈。
在連接數(shù)不多的情況下,傳統(tǒng)IO編寫容易屋匕、方便使用葛碧。但是隨著連接數(shù)的增多,問題傳統(tǒng)IO就不行了过吻。因為傳統(tǒng)IO處理每個連接都要消耗一個線程进泼,而程序的效率當(dāng)線程數(shù)不多時是隨著線程數(shù)的增加而增加,但是到一定的數(shù)量之后纤虽,是隨著線程數(shù)的增加而減少陷谱。所以傳統(tǒng)阻塞式IO的 瓶頸在于不能處理過多的連接饲做。
非阻塞式IO的出現(xiàn)的目的就是為了解決這個瓶頸基协。而非阻塞式IO是怎么實(shí)現(xiàn)的呢蜘渣?非阻塞IO處理連接的線程數(shù)和連接數(shù)沒有聯(lián)系,也就是說處理10000個 連接非阻塞IO不需要10000個線程杰刽,你可以用1000個也可以用2000個線程來處理菠发。因為非阻塞IO處理連接是異步的。當(dāng)某個連接發(fā)送請求到服務(wù) 器贺嫂,服務(wù)器把這個連接請求當(dāng)作一個請求"事件"滓鸠,并把這個"事件"分配給相應(yīng)的函數(shù)處理。我們可以把這個處理函數(shù)放到線程中去執(zhí)行第喳,執(zhí)行完就把線程歸還糜俗。 這樣一個線程就可以異步的處理多個事件。而阻塞式IO的線程的大部分時間都浪費(fèi)在等待請求上了。
然后NIO的非阻塞悠抹,需要一直輪詢寞射,也是一個比較耗資源的,所以出現(xiàn)AIO 锌钮。
BIO、NIO引矩、AIO適用場景
** BIO方式適用于連接數(shù)目比較小且固定的架構(gòu)梁丘,這種方式對服務(wù)器資源要求比較高,并發(fā)局限于應(yīng)用中旺韭,JDK1.4以前的唯一選擇氛谜,但程序直觀簡單易理解。**
**NIO方式適用于連接數(shù)目多且連接比較短(輕操作)的架構(gòu)区端,比如聊天服務(wù)器值漫,并發(fā)局限于應(yīng)用中,編程比較復(fù)雜织盼,JDK1.4開始支持杨何。 **
AIO方式使用于連接數(shù)目多且連接比較長(重操作)的架構(gòu),比如相冊服務(wù)器沥邻,充分調(diào)用OS參與并發(fā)操作危虱,編程比較復(fù)雜,JDK7開始支持唐全。