【Java基礎(chǔ)】- IO 學(xué)習(xí)

JAVA IO

Java IO 即 Java 輸入輸出。在開發(fā)應(yīng)用軟件時(shí)议惰,很多時(shí)候都需要和各種輸入輸出相關(guān)的媒介打交道揽咕。與媒介進(jìn)行 IO 操作的過程十分復(fù)雜,需要考慮眾多因素粟关,比如:進(jìn)行 IO 操作媒介的類型(文件疮胖、控制臺(tái)、網(wǎng)絡(luò))闷板、通信方式(順序澎灸、隨機(jī)、二進(jìn)制遮晚、按字符性昭、按字、按行等等)县遣。

Java 類庫提供了相應(yīng)的類來解決這些難題糜颠,這些類就位于 java.io 包中, 在整個(gè) java.io 包中最重要的就是 5 個(gè)類和一個(gè)接口萧求。5 個(gè)類指的是 File其兴、OutputStream、InputStream夸政、Writer元旬、Reader;一個(gè)接口指的是 Serializable秒梳。

由于老的 Java IO 標(biāo)準(zhǔn)類提供 IO 操作(如 read()法绵,write())都是同步阻塞的,因此酪碘,IO 通常也被稱為阻塞 IO(即 BIO朋譬,Blocking I/O)。

JAVA-NIO

在 JDK1.4 之后兴垦,為了提高 Java IO 的效率徙赢,Java 又提供了一套 New IO(NIO)字柠,原因在于它相對(duì)于之前的 IO 類庫是新增的。此外狡赐,舊的 IO 類庫提供的 IO 方法是阻塞的窑业,New IO 類庫則讓 Java 可支持非阻塞 IO,所以枕屉,更多的人喜歡稱之為非阻塞 IO(Non-blocking IO)常柄。

*注意:異步只有異步,同步才有阻塞和非阻塞的說法搀擂!

IO模型

  1. 阻塞式IO(blocking IO)西潘,即傳統(tǒng)的IO模型
  2. 非阻塞式IO( non-blocking IO),默認(rèn)創(chuàng)建的socket都是阻塞的
  3. IO多路復(fù)用(IO multiplexing) 哨颂,即經(jīng)典的Reactor設(shè)計(jì)模式喷市,有時(shí)也稱為異步阻塞IO
  4. 異步IO(asynchronous IO),即經(jīng)典的Proactor設(shè)計(jì)模式威恼,也稱為異步非阻塞IO
  5. 信號(hào)驅(qū)動(dòng)式IO(signal driven IO)

IO操作品姓,主要分為兩部分

  1. 數(shù)據(jù)準(zhǔn)備,將數(shù)據(jù)加載到內(nèi)核緩存(數(shù)據(jù)加載到操作系統(tǒng))
  2. 將內(nèi)核緩存中的數(shù)據(jù)加載到用戶緩存(從操作系統(tǒng)復(fù)制到應(yīng)用中)

同步和異步的概念描述的是用戶線程與內(nèi)核的交互方式箫措。
阻塞和非阻塞的概念描述的是用戶線程調(diào)用內(nèi)核IO操作的方式腹备。

同步阻塞IO

同步阻塞IO模型是最簡(jiǎn)單的IO模型,用戶線程在內(nèi)核進(jìn)行IO操作時(shí)被阻塞


image.png

用戶線程通過系統(tǒng)調(diào)用read發(fā)起IO讀操作蒂破,由用戶控件轉(zhuǎn)到內(nèi)核空間馏谨。
內(nèi)核等到數(shù)據(jù)包到達(dá)后别渔,然后將接收的數(shù)據(jù)拷貝到用戶空間附迷,完成read操作。

同步非阻塞IO

同步阻塞IO是在同步阻塞IO的基礎(chǔ)上哎媚,將socket設(shè)置為NIO(NOBLOCK)喇伯。
這樣做用戶線程可以在發(fā)起IO請(qǐng)求后可以立即返回。


image.png

由于socket是非阻塞的方式拨与,因此用戶線程發(fā)起IO請(qǐng)求時(shí)立即返回稻据。
但未讀取到任何數(shù)據(jù),用戶線程需要不斷地發(fā)起IO請(qǐng)求买喧,直到數(shù)據(jù)到達(dá)后捻悯,才真正讀取數(shù)據(jù),繼續(xù)執(zhí)行淤毛。

IO多路復(fù)用

IO多路復(fù)用模型是建立在內(nèi)核提供的多路分離函數(shù)select基礎(chǔ)之上的今缚。
使用select函數(shù)可以避免同步非阻塞IO模型中輪詢等待的問題。


image.png

用戶首先將需要進(jìn)行IO操作的socket添加到select中低淡,然后阻塞等待select系統(tǒng)調(diào)用返回姓言。
當(dāng)數(shù)據(jù)到達(dá)時(shí)瞬项,socket被激活,select函數(shù)返回何荚。用戶線程正式發(fā)起read請(qǐng)求囱淋,讀取數(shù)據(jù)并繼續(xù)執(zhí)行。

從流程上來看餐塘,使用select函數(shù)進(jìn)行IO請(qǐng)求和同步阻塞模型沒有太大的區(qū)別妥衣,
甚至還多了添加監(jiān)視socket,以及調(diào)用select函數(shù)的額外操作戒傻,效率更差称鳞。
但是,使用select以后最大的優(yōu)勢(shì)是用戶可以在一個(gè)線程內(nèi)同時(shí)處理多個(gè)socket的IO請(qǐng)求稠鼻。
用戶可以注冊(cè)多個(gè)socket冈止,然后不斷地調(diào)用select讀取被激活的socket,即可達(dá)到在同一個(gè)線程內(nèi)同時(shí)處理多個(gè)IO請(qǐng)求的目的候齿。
而在同步阻塞模型中熙暴,必須通過多線程的方式才能達(dá)到這個(gè)目的。

然而慌盯,使用select函數(shù)的優(yōu)點(diǎn)并不僅限于此周霉。
雖然上述方式允許單線程內(nèi)處理多個(gè)IO請(qǐng)求,但是每個(gè)IO請(qǐng)求的過程還是阻塞的(在select函數(shù)上阻塞)亚皂,平均時(shí)間甚至比同步阻塞IO模型還要長(zhǎng)俱箱。
如果用戶線程只注冊(cè)自己感興趣的socket或者IO請(qǐng)求,然后去做自己的事情灭必,等到數(shù)據(jù)到來時(shí)再進(jìn)行處理狞谱,則可以提高CPU的利用率。

IO多路復(fù)用模型使用了Reactor設(shè)計(jì)模式實(shí)現(xiàn)了這一機(jī)制禁漓。

首先跟衅,要從你常用的IO操作談起,比如read和write播歼,通常IO操作都是阻塞I/O的伶跷,也就是說當(dāng)你調(diào)用read時(shí),
如果沒有數(shù)據(jù)收到秘狞,那么線程或者進(jìn)程就會(huì)被掛起叭莫,直到收到數(shù)據(jù)。

這樣烁试,當(dāng)服務(wù)器需要處理1000個(gè)連接的的時(shí)候雇初,而且只有很少連接忙碌的,
那么會(huì)需要1000個(gè)線程或進(jìn)程來處理1000個(gè)連接廓潜,而1000個(gè)線程大部分是被阻塞起來的抵皱。
由于CPU的核數(shù)或超線程數(shù)一般都不大善榛,比如4,8,16,32,64,128,比如4個(gè)核要跑1000個(gè)線程呻畸,那么每個(gè)線程的時(shí)間槽非常短移盆,而線程切換非常頻繁。
這樣是有問題的:
1伤为,線程是有內(nèi)存開銷的咒循,1個(gè)線程可能需要512K(或2M)存放棧,那么1000個(gè)線程就要512M(或2G)內(nèi)存绞愚。
2叙甸,線程的切換,或者說上下文切換是有CPU開銷的位衩,當(dāng)大量時(shí)間花在上下文切換的時(shí)候裆蒸,分配給真正的操作的CPU就要少很多。

那么糖驴,我們就要引入非阻塞I/O的概念僚祷,非阻塞IO很簡(jiǎn)單,通過fcntl(POSIX)或ioctl(Unix)設(shè)為非阻塞模式贮缕,
這時(shí)辙谜,當(dāng)你調(diào)用read時(shí),如果有數(shù)據(jù)收到感昼,就返回?cái)?shù)據(jù)装哆,如果沒有數(shù)據(jù)收到,就立刻返回一個(gè)錯(cuò)誤定嗓,如EWOULDBLOCK蜕琴。
這樣是不會(huì)阻塞線程了,但是你還是要不斷的輪詢來讀取或?qū)懭搿?/p>

于是蜕乡,我們需要引入IO多路復(fù)用的概念奸绷。
多路復(fù)用是指使用一個(gè)線程來檢查多個(gè)文件描述符(Socket)的就緒狀態(tài)梗夸,比如調(diào)用select和poll函數(shù)层玲,傳入多個(gè)文件描述符,
如果有一個(gè)文件描述符就緒反症,則返回辛块,否則阻塞直到超時(shí)。
得到就緒狀態(tài)后進(jìn)行真正的操作可以在同一個(gè)線程里執(zhí)行铅碍,也可以啟動(dòng)線程執(zhí)行(比如使用線程池)润绵。

這樣在處理1000個(gè)連接時(shí),只需要1個(gè)線程監(jiān)控就緒狀態(tài)胞谈,對(duì)就緒的每個(gè)連接開一個(gè)線程處理就可以了尘盼,
這樣需要的線程數(shù)大大減少憨愉,減少了內(nèi)存開銷和上下文切換的CPU開銷。

異步IO

“真正”的異步IO需要操作系統(tǒng)更強(qiáng)的支持卿捎。
在IO多路復(fù)用模型中配紫,事件循環(huán)將文件句柄的狀態(tài)事件通知給用戶線程,由用戶線程自行讀取數(shù)據(jù)午阵、處理數(shù)據(jù)躺孝。
而在異步IO模型中,當(dāng)用戶線程收到通知時(shí)底桂,數(shù)據(jù)已經(jīng)被內(nèi)核讀取完畢植袍,并放在了用戶線程指定的緩沖區(qū)內(nèi),內(nèi)核在IO完成后通知用戶線程直接使用即可籽懦。


image.png

異步IO模型使用了Proactor設(shè)計(jì)模式實(shí)現(xiàn)了這一機(jī)制于个。

相比于IO多路復(fù)用模型,異步IO并不十分常用暮顺,不少高性能并發(fā)服務(wù)程序使用IO多路復(fù)用模型+多線程任務(wù)處理的架構(gòu)基本可以滿足需求嘹锁。
況且目前操作系統(tǒng)對(duì)異步IO的支持并非特別完善,更多的是采用IO多路復(fù)用模型模擬異步IO的方式
(IO事件觸發(fā)時(shí)不直接通知用戶線程七咧,而是將數(shù)據(jù)讀寫完畢后放到用戶指定的緩沖區(qū)中)踏施。
Java7之后已經(jīng)支持了異步IO,感興趣的讀者可以嘗試使用宙项。

參考博文:
https://www.cnblogs.com/straybirds/p/9479158.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末乏苦,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子尤筐,更是在濱河造成了極大的恐慌汇荐,老刑警劉巖,帶你破解...
    沈念sama閱讀 223,207評(píng)論 6 521
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盆繁,死亡現(xiàn)場(chǎng)離奇詭異掀淘,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)油昂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,455評(píng)論 3 400
  • 文/潘曉璐 我一進(jìn)店門革娄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人冕碟,你說我怎么就攤上這事拦惋。” “怎么了安寺?”我有些...
    開封第一講書人閱讀 170,031評(píng)論 0 366
  • 文/不壞的土叔 我叫張陵厕妖,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我挑庶,道長(zhǎng)言秸,這世上最難降的妖魔是什么软能? 我笑而不...
    開封第一講書人閱讀 60,334評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮举畸,結(jié)果婚禮上埋嵌,老公的妹妹穿的比我還像新娘。我一直安慰自己俱恶,他們只是感情好雹嗦,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,322評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著合是,像睡著了一般了罪。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上聪全,一...
    開封第一講書人閱讀 52,895評(píng)論 1 314
  • 那天泊藕,我揣著相機(jī)與錄音,去河邊找鬼难礼。 笑死娃圆,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蛾茉。 我是一名探鬼主播讼呢,決...
    沈念sama閱讀 41,300評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼谦炬!你這毒婦竟也來了悦屏?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,264評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤键思,失蹤者是張志新(化名)和其女友劉穎础爬,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吼鳞,經(jīng)...
    沈念sama閱讀 46,784評(píng)論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡看蚜,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,870評(píng)論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了赔桌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片供炎。...
    茶點(diǎn)故事閱讀 40,989評(píng)論 1 354
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖纬乍,靈堂內(nèi)的尸體忽然破棺而出碱茁,到底是詐尸還是另有隱情,我是刑警寧澤仿贬,帶...
    沈念sama閱讀 36,649評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站墓贿,受9級(jí)特大地震影響茧泪,放射性物質(zhì)發(fā)生泄漏蜓氨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,331評(píng)論 3 336
  • 文/蒙蒙 一队伟、第九天 我趴在偏房一處隱蔽的房頂上張望穴吹。 院中可真熱鬧,春花似錦嗜侮、人聲如沸港令。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,814評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽顷霹。三九已至,卻和暖如春击吱,著一層夾襖步出監(jiān)牢的瞬間淋淀,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,940評(píng)論 1 275
  • 我被黑心中介騙來泰國(guó)打工覆醇, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留朵纷,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,452評(píng)論 3 379
  • 正文 我出身青樓永脓,卻偏偏與公主長(zhǎng)得像袍辞,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子常摧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,995評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容