百度橙数、騰訊熱門面試題:聊聊Unix與Java的IO模型?(含詳細(xì)解析)

眾所周知

如果去百度帅戒、騰訊等一線大廠面試商模,一定會(huì)深入考候選人的基礎(chǔ)技術(shù)功底,其中尤為關(guān)鍵和重視的就是IO相關(guān)的技術(shù)和知識(shí)蜘澜。

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

同步與異步

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

比如現(xiàn)在我們的程序想要通過網(wǎng)絡(luò)讀取數(shù)據(jù)装诡,如果是阻塞IO模式,一旦發(fā)起請(qǐng)求到操作系統(tǒng)內(nèi)核去從網(wǎng)絡(luò)中讀取數(shù)據(jù)践盼,就會(huì)阻塞在那里鸦采,必須要等待網(wǎng)絡(luò)中的數(shù)據(jù)到達(dá)了之后,才能從網(wǎng)絡(luò)讀取數(shù)據(jù)到內(nèi)核咕幻,再從內(nèi)核返回給程序渔伯,如下圖。


非阻塞肄程,指的就是程序發(fā)送請(qǐng)求給內(nèi)核要從網(wǎng)絡(luò)讀取數(shù)據(jù)锣吼,但是此時(shí)網(wǎng)絡(luò)中的數(shù)據(jù)還沒到,此時(shí)不會(huì)阻塞住蓝厌,內(nèi)核會(huì)返回一個(gè)異常消息給程序玄叠。

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

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



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

“同步/異步”更多的是針對(duì)比如接口調(diào)用互墓,服務(wù)調(diào)用,API類庫調(diào)用蒋搜,類似這樣的場景篡撵。

而“阻塞/非阻塞”概念針對(duì)的是底層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ā)起請(qǐng)求之后會(huì)阻塞,一直到系統(tǒng)內(nèi)核發(fā)現(xiàn)網(wǎng)絡(luò)中有數(shù)據(jù)到達(dá)了娘侍,拷貝數(shù)據(jù)給程序進(jìn)程了咖刃,才能返回
  2. 非阻塞IO:就是上面圖里的那種非阻塞IO模式,程序發(fā)起請(qǐng)求讀取數(shù)據(jù)憾筏,系統(tǒng)內(nèi)核發(fā)現(xiàn)網(wǎng)絡(luò)數(shù)據(jù)還沒到嚎杨,就返回一個(gè)異常信息,程序不會(huì)阻塞在IO操作上氧腰,但是過一會(huì)兒還得再來發(fā)起請(qǐng)求給內(nèi)核枫浙,直到內(nèi)核發(fā)現(xiàn)網(wǎng)絡(luò)數(shù)據(jù)到達(dá)了,此時(shí)就會(huì)拷貝數(shù)據(jù)給程序進(jìn)程
  3. IO多路復(fù)用:這個(gè)下面來講
  4. 信號(hào)驅(qū)動(dòng)式IO:一般很少用到古拴,這里不說明
  5. 異步IO:下面來講
JDK 1.4之前的同步阻塞IO

在JDK 1.4之前箩帚,主要就是同步阻塞IO模型,在Java里叫做BIO黄痪。

在Java代碼里調(diào)用IO相關(guān)接口单起,發(fā)起IO操作之后导披,Java程序就會(huì)同步等待,這個(gè)同步指的是Java程序調(diào)用IO API接口的層面而言。

而IO API在底層的IO操作是基于阻塞IO來的痹筛,向操作系統(tǒng)內(nèi)核發(fā)起IO請(qǐng)求壶辜,系統(tǒng)內(nèi)核會(huì)等待數(shù)據(jù)就位之后泞坦,才會(huì)執(zhí)行IO操作肮蛹,執(zhí)行完畢了才會(huì)返回。

JDK 1.4之后的同步非阻塞NIO

在JDK 1.4之后提供了NIO潦嘶,他的概念是同步非阻塞涩嚣,也就是說如果你調(diào)用NIO接口去執(zhí)行IO操作崇众,其實(shí)還是同步等待的,但是在底層的IO操作上 航厚,會(huì)對(duì)系統(tǒng)內(nèi)核發(fā)起非阻塞IO請(qǐng)求顷歌,以非阻塞的形式來執(zhí)行IO。

也就是說幔睬,如果底層數(shù)據(jù)沒到位眯漩,那么內(nèi)核返回異常信息,不會(huì)阻塞住麻顶,但是NIO接口內(nèi)部會(huì)采用非阻塞方式過一會(huì)兒再次調(diào)用內(nèi)核發(fā)起IO請(qǐng)求赦抖,直到成功為止。

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

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

實(shí)際上要尔,如果基于NIO進(jìn)行網(wǎng)絡(luò)通信,采取的就是多路復(fù)用的IO模型新娜,這個(gè)多路復(fù)用IO模型針對(duì)的是網(wǎng)絡(luò)通信中的IO場景來說的赵辕。

簡單來說,就是在基于Socket進(jìn)行網(wǎng)絡(luò)通信的時(shí)候概龄,如果有多個(gè)客戶端跟你的服務(wù)端建立了Socket連接还惠,那你就需要維護(hù)多個(gè)Socket連接。

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

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

接著你就要同步等著select函數(shù)去對(duì)底層的多個(gè) Socket 連接進(jìn)行輪詢颜矿,不斷的查看各個(gè) Socket 連接誰有請(qǐng)求到達(dá)寄猩,就可以讓select函數(shù)返回,交給我們的Java程序來處理骑疆。

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

然后select函數(shù)可以輪詢下一個(gè)Socket泊柬,不會(huì)阻塞在某個(gè)Socket上,所以底層是基于這種非阻塞的模式來“監(jiān)視”各個(gè)Socket誰有數(shù)據(jù)到達(dá)的诈火。

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

通過這種IO多路復(fù)用的模型惊科,就可以用一個(gè)線程,調(diào)用一個(gè)select函數(shù)亮钦,然后監(jiān)視大量的客戶端連接了馆截,如下圖。


AIO以及異步IO模型

最后就是JDK 1.7之后蜂莉,又支持了AIO蜡娶,也叫做NIO 2.0,他就支持異步IO模型了巡语。

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

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

此時(shí)不需要去管這個(gè)IO是否成功了枢赔,AIO接口會(huì)直接返回澄阳,你的Java程序也會(huì)直接返回。

然后踏拜,你的Java程序就可以去干別的事兒了碎赢。大家聯(lián)想一下上面說的那個(gè)異步的例子,就可以理解這里為什么叫做異步了速梗。

因?yàn)锽IO肮塞、NIO都是同步的,你發(fā)起IO請(qǐng)求姻锁,都必須同步等待IO操作完成枕赵。

但是這里你發(fā)起一個(gè)IO請(qǐng)求,直接AIO接口就返回了位隶,你就可以干別的事兒了拷窜,純異步的方式。

不過你需要提供一個(gè)回調(diào)函數(shù)給AIO接口涧黄,一旦底層系統(tǒng)內(nèi)核完成了具體的IO請(qǐng)求篮昧,比如網(wǎng)絡(luò)讀寫之類的,就會(huì)回調(diào)你提供的回調(diào)函數(shù)笋妥。

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

整個(gè)過程如下圖:


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末春宣,一起剝皮案震驚了整個(gè)濱河市疚颊,隨后出現(xiàn)的幾起案子狈孔,更是在濱河造成了極大的恐慌,老刑警劉巖材义,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件均抽,死亡現(xiàn)場離奇詭異,居然都是意外死亡其掂,警方通過查閱死者的電腦和手機(jī)油挥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來款熬,“玉大人深寥,你說我怎么就攤上這事∠团#” “怎么了惋鹅?”我有些...
    開封第一講書人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長殉簸。 經(jīng)常有香客問我闰集,道長,這世上最難降的妖魔是什么般卑? 我笑而不...
    開封第一講書人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任武鲁,我火速辦了婚禮,結(jié)果婚禮上蝠检,老公的妹妹穿的比我還像新娘沐鼠。我一直安慰自己,他們只是感情好叹谁,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開白布饲梭。 她就那樣靜靜地躺著焰檩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪锅尘。 梳的紋絲不亂的頭發(fā)上布蔗,一...
    開封第一講書人閱讀 49,772評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音顿乒,去河邊找鬼泽谨。 笑死特漩,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的骨杂。 我是一名探鬼主播涂身,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼搓蚪!你這毒婦竟也來了蛤售?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤妒潭,失蹤者是張志新(化名)和其女友劉穎悴能,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體雳灾,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡漠酿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了谎亩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片炒嘲。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖团驱,靈堂內(nèi)的尸體忽然破棺而出摸吠,到底是詐尸還是另有隱情,我是刑警寧澤嚎花,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布寸痢,位于F島的核電站,受9級(jí)特大地震影響紊选,放射性物質(zhì)發(fā)生泄漏啼止。R本人自食惡果不足惜献烦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一巩那、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧裆赵,春花似錦页藻、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽朦促。三九已至务冕,卻和暖如春禀忆,著一層夾襖步出監(jiān)牢的瞬間箩退,已是汗流浹背戴涝。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留可帽,地道東北人映跟。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像剃法,于是被迫代替她去往敵國和親路鹰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子晋柱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

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