<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          常見的 IO 模型有哪些?Java 中 BIO、NIO、AIO 的區(qū)別?

          共 2982字,需瀏覽 6分鐘

           ·

          2021-02-10 21:54

          IO 模型這塊確實挺難理解的,需要太多計算機底層知識。寫這篇文章用了挺久,就非常希望能把我所知道的講出來吧!希望朋友們能有收貨!為了寫這篇文章,還翻看了一下《UNIX 網(wǎng)絡(luò)編程》這本書,太難了,我滴乖乖!心痛~

          個人能力有限。如果文章有任何需要補充/完善/修改的地方,歡迎在評論區(qū)指出,共同進步!

          相關(guān)閱讀(原創(chuàng)):淘寶一面:“說一下 Spring Boot 自動裝配原理唄?”?

          前言

          I/O 一直是很多小伙伴難以理解的一個知識點,這篇文章我會將我所理解的 I/O 講給你聽,希望可以對你有所幫助。

          I/O

          何為 I/O?

          I/O(Input/Outpu) 即輸入/輸出

          我們先從計算機結(jié)構(gòu)的角度來解讀一下 I/O。

          根據(jù)馮.諾依曼結(jié)構(gòu),計算機結(jié)構(gòu)分為 5 大部分:運算器、控制器、存儲器、輸入設(shè)備、輸出設(shè)備。

          馮諾依曼體系結(jié)構(gòu)

          輸入設(shè)備(比如鍵盤)和輸出設(shè)備(比如鼠標)都屬于外部設(shè)備。網(wǎng)卡、硬盤這種既可以屬于輸入設(shè)備,也可以屬于輸出設(shè)備。

          輸入設(shè)備向計算機輸入數(shù)據(jù),輸出設(shè)備接收計算機輸出的數(shù)據(jù)。

          從計算機結(jié)構(gòu)的視角來看的話, I/O 描述了計算機系統(tǒng)與外部設(shè)備之間通信的過程。

          我們再先從應用程序的角度來解讀一下 I/O。

          根據(jù)大學里學到的操作系統(tǒng)相關(guān)的知識:為了保證操作系統(tǒng)的穩(wěn)定性和安全性,一個進程的地址空間劃分為 用戶空間(User space)內(nèi)核空間(Kernel space )

          像我們平常運行的應用程序都是運行在用戶空間,只有內(nèi)核空間才能進行系統(tǒng)態(tài)級別的資源有關(guān)的操作,比如如文件管理、進程通信、內(nèi)存管理等等。也就是說,我們想要進行 IO 操作,一定是要依賴內(nèi)核空間的能力。

          并且,用戶空間的程序不能直接訪問內(nèi)核空間。

          當想要執(zhí)行 IO 操作時,由于沒有執(zhí)行這些操作的權(quán)限,只能發(fā)起系統(tǒng)調(diào)用請求操作系統(tǒng)幫忙完成。

          因此,用戶進程想要執(zhí)行 IO 操作的話,必須通過 系統(tǒng)調(diào)用 來間接訪問內(nèi)核空間

          我們在平常開發(fā)過程中接觸最多的就是 磁盤 IO(讀寫文件)網(wǎng)絡(luò) IO(網(wǎng)絡(luò)請求和相應)

          從應用程序的視角來看的話,我們的應用程序?qū)Σ僮飨到y(tǒng)的內(nèi)核發(fā)起 IO 調(diào)用(系統(tǒng)調(diào)用),操作系統(tǒng)負責的內(nèi)核執(zhí)行具體的 IO 操作。也就是說,我們的應用程序?qū)嶋H上只是發(fā)起了 IO 操作的調(diào)用而已,具體 IO 的執(zhí)行是由操作系統(tǒng)的內(nèi)核來完成的。

          當應用程序發(fā)起 I/O 調(diào)用后,會經(jīng)歷兩個步驟:

          1. 內(nèi)核等待 I/O 設(shè)備準備好數(shù)據(jù)
          2. 內(nèi)核將數(shù)據(jù)從內(nèi)核空間拷貝到用戶空間。

          有哪些常見的 IO 模型?

          UNIX 系統(tǒng)下, IO 模型一共有 5 種:同步阻塞 I/O同步非阻塞 I/OI/O 多路復用信號驅(qū)動 I/O異步 I/O

          這也是我們經(jīng)常提到的 5 種 IO 模型。

          Java 中 3 種常見 IO 模型

          BIO (Blocking I/O)

          BIO 屬于同步阻塞 IO 模型

          同步阻塞 IO 模型中,應用程序發(fā)起 read 調(diào)用后,會一直阻塞,直到在內(nèi)核把數(shù)據(jù)拷貝到用戶空間。

          圖源:《深入拆解Tomcat & Jetty》

          在客戶端連接數(shù)量不高的情況下,是沒問題的。但是,當面對十萬甚至百萬級連接的時候,傳統(tǒng)的 BIO 模型是無能為力的。因此,我們需要一種更高效的 I/O 處理模型來應對更高的并發(fā)量。

          NIO (Non-blocking/New I/O)

          Java 中的 NIO 于 Java 1.4 中引入,對應 java.nio 包,提供了 Channel , SelectorBuffer 等抽象。NIO 中的 N 可以理解為 Non-blocking,不單純是 New。它支持面向緩沖的,基于通道的 I/O 操作方法。對于高負載、高并發(fā)的(網(wǎng)絡(luò))應用,應使用 NIO 。

          Java 中的 NIO 可以看作是 I/O 多路復用模型。也有很多人認為,Java 中的 NIO 屬于同步非阻塞 IO 模型。

          跟著我的思路往下看看,相信你會得到答案!

          我們先來看看 同步非阻塞 IO 模型

          圖源:《深入拆解Tomcat & Jetty》

          同步非阻塞 IO 模型中,應用程序會一直發(fā)起 read 調(diào)用,等待數(shù)據(jù)從內(nèi)核空間拷貝到用戶空間的這段時間里,線程依然是阻塞的,直到在內(nèi)核把數(shù)據(jù)拷貝到用戶空間。

          相比于同步阻塞 IO 模型,同步非阻塞 IO 模型確實有了很大改進。通過輪詢操作,避免了一直阻塞。

          但是,這種 IO 模型同樣存在問題:應用程序不斷進行 I/O 系統(tǒng)調(diào)用輪詢數(shù)據(jù)是否已經(jīng)準備好的過程是十分消耗 CPU 資源的。

          這個時候,I/O 多路復用模型 就上場了。

          IO 多路復用模型中,線程首先發(fā)起 select 調(diào)用,詢問內(nèi)核數(shù)據(jù)是否準備就緒,等內(nèi)核把數(shù)據(jù)準備好了,用戶線程再發(fā)起 read 調(diào)用。read 調(diào)用的過程(數(shù)據(jù)從內(nèi)核空間->用戶空間)還是阻塞的。

          目前支持 IO 多路復用的系統(tǒng)調(diào)用,有 select,epoll 等等。select 系統(tǒng)調(diào)用,是目前幾乎在所有的操作系統(tǒng)上都有支持

          • select 調(diào)用 :內(nèi)核提供的系統(tǒng)調(diào)用,它支持一次查詢多個系統(tǒng)調(diào)用的可用狀態(tài)。幾乎所有的操作系統(tǒng)都支持。
          • epoll 調(diào)用 :linux 2.6 內(nèi)核,屬于 select 調(diào)用的增強版本,優(yōu)化了 IO 的執(zhí)行效率。

          IO 多路復用模型,通過減少無效的系統(tǒng)調(diào)用,減少了對 CPU 資源的消耗。

          Java 中的 NIO ,有一個非常重要的選擇器 ( Selector ) 的概念,也可以被稱為 多路復用器。通過它,只需要一個線程便可以管理多個客戶端連接。當客戶端數(shù)據(jù)到了之后,才會為其服務(wù)。

          AIO (Asynchronous I/O)

          AIO 也就是 NIO 2。Java 7 中引入了 NIO 的改進版 NIO 2,它是異步 IO 模型。

          異步 IO 是基于事件和回調(diào)機制實現(xiàn)的,也就是應用操作之后會直接返回,不會堵塞在那里,當后臺處理完成,操作系統(tǒng)會通知相應的線程進行后續(xù)的操作。

          目前來說 AIO 的應用還不是很廣泛。Netty 之前也嘗試使用過 AIO,不過又放棄了。這是因為,Netty 使用了 AIO 之后,在 Linux 系統(tǒng)上的性能并沒有多少提升。

          最后,來一張圖,簡單總結(jié)一下 Java 中的 BIO、NIO、AIO。

          參考

          • 《深入拆解 Tomcat & Jetty》
          • 如何完成一次 IO:https://llc687.top/post/如何完成一次-io/
          • 程序員應該這樣理解 IO:https://www.jianshu.com/p/fa7bdc4f3de7
          • 10 分鐘看懂, Java NIO 底層原理:https://www.cnblogs.com/crazymakercircle/p/10225159.html
          • IO 模型知多少 | 理論篇:https://www.cnblogs.com/sheng-jie/p/how-much-you-know-about-io-models.html
          • 《UNIX 網(wǎng)絡(luò)編程 卷 1;套接字聯(lián)網(wǎng) API 》6.2 節(jié) IO 模型
          瀏覽 41
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  成人网视频在线 | 高潮喷水网址 | 成人无码欧美大片免费看 | 亚州在线播放 | 91精品人妻一区二区三区蜜桃 |