乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

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

       西北望msm66g9f 2019-10-21

      眾所周知,如果去百度、騰訊等一線大廠面試,一定會深入考候選人的基礎技術功底,其中尤為關鍵和重視的就是IO相關的技術和知識。

      而要搞明白IO相關的概念,首先就得弄清楚同步與異步,阻塞與非阻塞到底是什么意思。

      同步與異步

      想要搞明白IO模型,就先得搞明白“同步”與“異步”的關系。

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

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

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

      然后這個接口后續(xù)如果干完了自己的任務,比如寫完了文件或者是什么的,會反過來通知調用者,之前你的那個調用成功了。可以通過一些內部通信機制來通知,也可以通過回調函數(shù)來通知,如下圖。

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

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

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

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

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

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

      第二種選擇,你可以先回家干點兒別的,比如說洗衣服做飯之類的,然后過了一會兒,柜臺工作人員打通電話給庫房工作人員,查到香煙庫存了,就會打個電話給你,告訴你這個事兒。

      這就是“異步”,你跟柜臺工作人員說了這個事兒,就直接走了,干別的去了,柜臺工作人員后面完成他的任務之后,就會反過來打電話回調通知你。

      阻塞與非阻塞

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

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

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

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

      因為如果網(wǎng)絡中的數(shù)據(jù)還沒到位,是不會阻塞住程序的,需要程序自己不斷的輪詢內核去嘗試讀取數(shù)據(jù),所以這種IO就是非阻塞的。如下圖:

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

      “同步/異步”更多的是針對比如接口調用,服務調用,API類庫調用,類似這樣的場景。

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

      Unix支持的5種IO模型

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

      1. 阻塞IO:就是上面圖里的那種阻塞IO模式,程序發(fā)起請求之后會阻塞,一直到系統(tǒng)內核發(fā)現(xiàn)網(wǎng)絡中有數(shù)據(jù)到達了,拷貝數(shù)據(jù)給程序進程了,才能返回

      2. 非阻塞IO:就是上面圖里的那種非阻塞IO模式,程序發(fā)起請求讀取數(shù)據(jù),系統(tǒng)內核發(fā)現(xiàn)網(wǎng)絡數(shù)據(jù)還沒到,就返回一個異常信息,程序不會阻塞在IO操作上,但是過一會兒還得再來發(fā)起請求給內核,直到內核發(fā)現(xiàn)網(wǎng)絡數(shù)據(jù)到達了,此時就會拷貝數(shù)據(jù)給程序進程

      3. IO多路復用:這個下面來講

      4. 信號驅動式IO:一般很少用到,這里不說明

      5. 異步IO:下面來講

      JDK 1.4之前的同步阻塞IO

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

      在Java代碼里調用IO相關接口,發(fā)起IO操作之后,Java程序就會同步等待,這個同步指的是Java程序調用IO API接口的層面而言。

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

      JDK 1.4之后的同步非阻塞NIO

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

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

      但是之所以說是同步非阻塞,這里的“同步”指的就是因為在你的Java代碼調用NIO接口層面是同步的,你還是要同步等待底層IO操作真正完成了才可以返回,只不過在執(zhí)行底層IO的時候采用了非阻塞的方式來執(zhí)行罷了。

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

      實際上,如果基于NIO進行網(wǎng)絡通信,采取的就是多路復用的IO模型,這個多路復用IO模型針對的是網(wǎng)絡通信中的IO場景來說的。

      簡單來說,就是在基于Socket進行網(wǎng)絡通信的時候,如果有多個客戶端跟你的服務端建立了Socket連接,那你就需要維護多個Socket連接。

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

      這也是為什么說NIO一定是“同步”的,因為你必須在這里同步等待某個Socket連接有請求到來。

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

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

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

      這就是所謂的“同步非阻塞”,但是因為操作系統(tǒng)把上述工作都封裝在一個select函數(shù)調用里了,可以對多路Socket連接同時進行監(jiān)視,所以就把這種模型稱之為“IO多路復用”模型。

      通過這種IO多路復用的模型,就可以用一個線程,調用一個select函數(shù),然后監(jiān)視大量的客戶端連接了,如下圖。

      AIO以及異步IO模型

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

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

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

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

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

      因為BIO、NIO都是同步的,你發(fā)起IO請求,都必須同步等待IO操作完成。

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

      不過你需要提供一個回調函數(shù)給AIO接口,一旦底層系統(tǒng)內核完成了具體的IO請求,比如網(wǎng)絡讀寫之類的,就會回調你提供的回調函數(shù)。

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

      整個過程如下圖:

      End

       作者簡介:

        本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
        轉藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多