阿里、騰訊熱門面試題:聊聊Unix與Java的IO模型畅蹂?(含詳細(xì)解析)

眾所周知

如果去百度健无、騰訊等一線大廠面試,一定會深入考候選人的基礎(chǔ)技術(shù)功底液斜,其中尤為關(guān)鍵和重視的就是IO相關(guān)的技術(shù)和知識累贤。

而要搞明白IO相關(guān)的概念,首先就得弄清楚同步與異步少漆,阻塞與非阻塞到底是什么意思臼膏。

同步與異步

想要搞明白IO模型,就先得搞明白“同步”與“異步”的關(guān)系示损。

所謂的“同步”讶请,比如說調(diào)用者去調(diào)用一個接口,這個接口比如要執(zhí)行一些磁盤文件讀寫操作,或者是網(wǎng)絡(luò)通信操作夺溢。

假設(shè)是“同步”的模式论巍,調(diào)用者必須要等待這個接口的磁盤讀寫或者網(wǎng)絡(luò)通信的操作執(zhí)行完畢了,調(diào)用者才能返回风响,這就是“同步”嘉汰,如下圖所示:


所謂的“異步”,就是說這個調(diào)用者調(diào)用接口之后状勤,直接就返回了鞋怀,他去干別的事兒了,也不管那個接口的磁盤讀寫或者是網(wǎng)絡(luò)通信是否成功持搜。

然后這個接口后續(xù)如果干完了自己的任務(wù)密似,比如寫完了文件或者是什么的,會反過來通知調(diào)用者葫盼,之前你的那個調(diào)用成功了残腌。可以通過一些內(nèi)部通信機(jī)制來通知贫导,也可以通過回調(diào)函數(shù)來通知抛猫,如下圖:


用生活中的例子理解同步與異步

如果給大家舉個生活中的例子,那么就可以用買煙這個事兒來舉個例子

比如說現(xiàn)在你要去一個柜臺買很多條香煙孩灯,但是現(xiàn)在柜臺沒那么多貨闺金,他需要打電話給庫房來查一下有沒有足夠的貨。

這個時候峰档,庫房的工作人員正好去吃飯了败匹,那現(xiàn)在你有兩種選擇

第一種選擇,你可以在柜臺等著讥巡,一直等待庫房工作人員回來哎壳,柜臺專員打通電話給他查到了庫存是否充足,你再走尚卫。

這個就是“同步”归榕,你找柜臺工作人員買香煙,他要打電話給庫房工作人員問庫存吱涉,如果你選擇“同步”模式刹泄,那么你就在柜臺一直等著,直到成功查詢到庫存為止怎爵。

第二種選擇特石,你可以先回家干點(diǎn)兒別的,比如說洗衣服做飯之類的鳖链,然后過了一會兒姆蘸,柜臺工作人員打通電話給庫房工作人員墩莫,查到香煙庫存了,就會打個電話給你逞敷,告訴你這個事兒狂秦。

這就是“異步”,你跟柜臺工作人員說了這個事兒推捐,就直接走了裂问,干別的去了,柜臺工作人員后面完成他的任務(wù)之后牛柒,就會反過來打電話回調(diào)通知你堪簿。

阻塞與非阻塞

實(shí)際上阻塞與非阻塞的概念,通常是針對底層的IO操作來說的皮壁。

比如現(xiàn)在我們的程序想要通過網(wǎng)絡(luò)讀取數(shù)據(jù)椭更,如果是阻塞IO模式,一旦發(fā)起請求到操作系統(tǒng)內(nèi)核去從網(wǎng)絡(luò)中讀取數(shù)據(jù)蛾魄,就會阻塞在那里虑瀑,必須要等待網(wǎng)絡(luò)中的數(shù)據(jù)到達(dá)了之后,才能從網(wǎng)絡(luò)讀取數(shù)據(jù)到內(nèi)核畏腕,再從內(nèi)核返回給程序,如下圖:


非阻塞茉稠,指的就是程序發(fā)送請求給內(nèi)核要從網(wǎng)絡(luò)讀取數(shù)據(jù)描馅,但是此時網(wǎng)絡(luò)中的數(shù)據(jù)還沒到,此時不會阻塞住而线,內(nèi)核會返回一個異常消息給程序铭污。

程序就可以干點(diǎn)兒別的,然后過一會兒再來發(fā)起一次請求給內(nèi)核膀篮,讓內(nèi)核嘗試從網(wǎng)絡(luò)讀取數(shù)據(jù)嘹狞。

因?yàn)槿绻W(wǎng)絡(luò)中的數(shù)據(jù)還沒到位,是不會阻塞住程序的誓竿,需要程序自己不斷的輪詢內(nèi)核去嘗試讀取數(shù)據(jù)磅网,所以這種IO就是非阻塞的。如下圖:



大家不要把“同步/異步”概念和“阻塞/非阻塞”概念混淆起來筷屡,實(shí)際上他們是兩組不同的概念涧偷。

“同步/異步”更多的是針對比如接口調(diào)用,服務(wù)調(diào)用毙死,API類庫調(diào)用燎潮,類似這樣的場景。

而“阻塞/非阻塞”概念針對的是底層IO操作的場景扼倘,比如磁盤IO确封,網(wǎng)絡(luò)IO。但是在Java IO模型里,兩種概念之間是有一定的關(guān)聯(lián)關(guān)系的 爪喘。

Unix支持的5種IO模型

Unix操作系統(tǒng)支持的IO模型主要就是5種:

  1. 阻塞IO:就是上面圖里的那種阻塞IO模式颜曾,程序發(fā)起請求之后會阻塞,一直到系統(tǒng)內(nèi)核發(fā)現(xiàn)網(wǎng)絡(luò)中有數(shù)據(jù)到達(dá)了腥放,拷貝數(shù)據(jù)給程序進(jìn)程了泛啸,才能返回
  2. 非阻塞IO:就是上面圖里的那種非阻塞IO模式,程序發(fā)起請求讀取數(shù)據(jù)秃症,系統(tǒng)內(nèi)核發(fā)現(xiàn)網(wǎng)絡(luò)數(shù)據(jù)還沒到候址,就返回一個異常信息,程序不會阻塞在IO操作上种柑,但是過一會兒還得再來發(fā)起請求給內(nèi)核岗仑,直到內(nèi)核發(fā)現(xiàn)網(wǎng)絡(luò)數(shù)據(jù)到達(dá)了,此時就會拷貝數(shù)據(jù)給程序進(jìn)程
  3. IO多路復(fù)用:這個下面來講
  4. 信號驅(qū)動式IO:一般很少用到聚请,這里不說明
  5. 異步IO:下面來講

JDK 1.4之前的同步阻塞IO

在JDK 1.4之前荠雕,主要就是同步阻塞IO模型,在Java里叫做BIO驶赏。

在Java代碼里調(diào)用IO相關(guān)接口炸卑,發(fā)起IO操作之后,Java程序就會同步等待煤傍,這個同步指的是Java程序調(diào)用IO API接口的層面而言盖文。

而IO API在底層的IO操作是基于阻塞IO來的,向操作系統(tǒng)內(nèi)核發(fā)起IO請求蚯姆,系統(tǒng)內(nèi)核會等待數(shù)據(jù)就位之后五续,才會執(zhí)行IO操作,執(zhí)行完畢了才會返回龄恋。

JDK 1.4之后的同步非阻塞NIO

在JDK 1.4之后提供了NIO疙驾,他的概念是同步非阻塞,也就是說如果你調(diào)用NIO接口去執(zhí)行IO操作郭毕,其實(shí)還是同步等待的它碎,但是在底層的IO操作上 ,會對系統(tǒng)內(nèi)核發(fā)起非阻塞IO請求显押,以非阻塞的形式來執(zhí)行IO链韭。

也就是說,如果底層數(shù)據(jù)沒到位煮落,那么內(nèi)核返回異常信息敞峭,不會阻塞住,但是NIO接口內(nèi)部會采用非阻塞方式過一會兒再次調(diào)用內(nèi)核發(fā)起IO請求蝉仇,直到成功為止旋讹。

但是之所以說是同步非阻塞殖蚕,這里的“同步”指的就是因?yàn)樵谀愕腏ava代碼調(diào)用NIO接口層面是同步的,你還是要同步等待底層IO操作真正完成了才可以返回沉迹,只不過在執(zhí)行底層IO的時候采用了非阻塞的方式來執(zhí)行罷了睦疫。

NIO網(wǎng)絡(luò)通信與IO多路復(fù)用模型

實(shí)際上,如果基于NIO進(jìn)行網(wǎng)絡(luò)通信鞭呕,采取的就是多路復(fù)用的IO模型蛤育,這個多路復(fù)用IO模型針對的是網(wǎng)絡(luò)通信中的IO場景來說的。

簡單來說葫松,就是在基于Socket進(jìn)行網(wǎng)絡(luò)通信的時候瓦糕,如果有多個客戶端跟你的服務(wù)端建立了Socket連接,那你就需要維護(hù)多個Socket連接腋么。

而所謂的多路復(fù)用IO模型咕娄,就是說你的Java代碼直接通過一個select函數(shù)調(diào)用,直接會進(jìn)入一個同步等待的狀態(tài)珊擂。

這也是為什么說NIO一定是“同步”的圣勒,因?yàn)槟惚仨氃谶@里同步等待某個Socket連接有請求到來。

接著你就要同步等著select函數(shù)去對底層的多個 Socket 連接進(jìn)行輪詢摧扇,不斷的查看各個 Socket 連接誰有請求到達(dá)圣贸,就可以讓select函數(shù)返回,交給我們的Java程序來處理扛稽。

select函數(shù)在底層會通過非阻塞的方式輪詢各個Socket吁峻,任何一個Socket如果沒有數(shù)據(jù)到達(dá),那么非阻塞的特性會立即返回一個信息庇绽。

然后select函數(shù)可以輪詢下一個Socket锡搜,不會阻塞在某個Socket上橙困,所以底層是基于這種非阻塞的模式來“監(jiān)視”各個Socket誰有數(shù)據(jù)到達(dá)的瞧掺。

這就是所謂的“同步非阻塞”,但是因?yàn)椴僮飨到y(tǒng)把上述工作都封裝在一個select函數(shù)調(diào)用里了凡傅,可以對多路Socket連接同時進(jìn)行監(jiān)視辟狈,所以就把這種模型稱之為“IO多路復(fù)用”模型

通過這種IO多路復(fù)用的模型夏跷,就可以用一個線程哼转,調(diào)用一個select函數(shù),然后監(jiān)視大量的客戶端連接了槽华,如下圖:


AIO以及異步IO模型

最后就是JDK 1.7之后壹蔓,又支持了AIO,也叫做NIO 2.0猫态,他就支持異步IO模型了佣蓉。

我們先說一下異步IO模型是什么意思披摄。

簡單來說,就是你的Java程序可以基于AIO API發(fā)起一個請求勇凭,比如說接收網(wǎng)絡(luò)數(shù)據(jù)疚膊,AIO API底層會基于異步IO模型來調(diào)用操作系統(tǒng)內(nèi)核。

此時不需要去管這個IO是否成功了虾标,AIO接口會直接返回寓盗,你的Java程序也會直接返回。

然后璧函,你的Java程序就可以去干別的事兒了傀蚌。大家聯(lián)想一下上面說的那個異步的例子,就可以理解這里為什么叫做異步了柳譬。

因?yàn)锽IO喳张、NIO都是同步的,你發(fā)起IO請求美澳,都必須同步等待IO操作完成销部。

但是這里你發(fā)起一個IO請求,直接AIO接口就返回了制跟,你就可以干別的事兒了舅桩,純異步的方式。

不過你需要提供一個回調(diào)函數(shù)給AIO接口雨膨,一旦底層系統(tǒng)內(nèi)核完成了具體的IO請求擂涛,比如網(wǎng)絡(luò)讀寫之類的,就會回調(diào)你提供的回調(diào)函數(shù)聊记。

比如說你要是通過網(wǎng)絡(luò)讀取數(shù)據(jù)撒妈,那么此時AIO接口就會把操作系統(tǒng)異步讀取到的數(shù)據(jù)交給你的回調(diào)函數(shù)。

整個過程如下圖:


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末排监,一起剝皮案震驚了整個濱河市狰右,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌舆床,老刑警劉巖棋蚌,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異挨队,居然都是意外死亡谷暮,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進(jìn)店門盛垦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來湿弦,“玉大人,你說我怎么就攤上這事腾夯〖瞻#” “怎么了赌蔑?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長竟秫。 經(jīng)常有香客問我娃惯,道長,這世上最難降的妖魔是什么肥败? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任趾浅,我火速辦了婚禮,結(jié)果婚禮上馒稍,老公的妹妹穿的比我還像新娘皿哨。我一直安慰自己,他們只是感情好纽谒,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布证膨。 她就那樣靜靜地躺著,像睡著了一般鼓黔。 火紅的嫁衣襯著肌膚如雪央勒。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天澳化,我揣著相機(jī)與錄音崔步,去河邊找鬼。 笑死缎谷,一個胖子當(dāng)著我的面吹牛井濒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播列林,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼瑞你,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了希痴?” 一聲冷哼從身側(cè)響起者甲,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎润梯,沒想到半個月后过牙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體甥厦,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡纺铭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了刀疙。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片舶赔。...
    茶點(diǎn)故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖谦秧,靈堂內(nèi)的尸體忽然破棺而出竟纳,到底是詐尸還是另有隱情撵溃,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布锥累,位于F島的核電站缘挑,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏桶略。R本人自食惡果不足惜语淘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望际歼。 院中可真熱鬧惶翻,春花似錦、人聲如沸鹅心。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽旭愧。三九已至颅筋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間输枯,已是汗流浹背垃沦。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留用押,地道東北人肢簿。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像蜻拨,于是被迫代替她去往敵國和親池充。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評論 2 359

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