面試題: AIO丶BIO丶NIO


Java 中 3 種常見 IO 模型

BIO (Blocking I/O)

BIO 屬於同步阻塞 IO 模型

同步阻塞 IO 模型中,應用程序發起 read 調用后,會一直阻塞,直到在內核把數據拷貝到用戶空間。

image-20210203174016160

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

NIO (Non-blocking/New I/O)

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

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

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

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

image-20210203174125435

同步非阻塞 IO 模型中,應用程序會一直發起 read 調用,等待數據從內核空間拷貝到用戶空間的這段時間里,線程依然是阻塞的,直到在內核把數據拷貝到用戶空間。

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

但是,這種 IO 模型同樣存在問題:應用程序不斷進行 I/O 系統調用輪詢數據是否已經准備好的過程是十分消耗 CPU 資源的。

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

image-20210203174151740

IO 多路復用模型中,線程首先發起 select 調用,詢問內核數據是否准備就緒,等內核把數據准備好了,用戶線程再發起 read 調用。read 調用的過程(數據從內核空間->用戶空間)還是阻塞的。

目前支持 IO 多路復用的系統調用,有 select,epoll 等等。select 系統調用,是目前幾乎在所有的操作系統上都有支持

  • select 調用 :內核提供的系統調用,它支持一次查詢多個系統調用的可用狀態。幾乎所有的操作系統都支持。
  • epoll 調用 :linux 2.6 內核,屬於 select 調用的增強版本,優化了 IO 的執行效率。

IO 多路復用模型,通過減少無效的系統調用,減少了對 CPU 資源的消耗。

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

image-20210203174218354

AIO (Asynchronous I/O)

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

異步 IO 是基於事件和回調機制實現的,也就是應用操作之后會直接返回,不會堵塞在那里,當后台處理完成,操作系統會通知相應的線程進行后續的操作。

image-20210203174242968

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

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

image-20210203174352092

BIO、NIO、AIO:

  • Java BIO : 同步並阻塞,服務器實現模式為一個連接一個線程,即客戶端有連接請求時服務器端就需要啟動一個線程進行處理,如果這個連接不做任何事情會造成不必要的線程開銷,當然可以通過線程池機制改善。
  • Java NIO : 同步非阻塞,服務器實現模式為一個請求一個線程,即客戶端發送的連接請求都會注冊到多路復用器上,多路復用器輪詢到連接有I/O請求時才啟動一個線程進行處理。
  • Java AIO(NIO.2) : 異步非阻塞,服務器實現模式為一個有效請求一個線程,客戶端的I/O請求都是由OS先完成了再通知服務器應用去啟動線程進行處理。

BIO、NIO、AIO適用場景分析:

  • BIO方式適用於連接數目比較小且固定的架構,這種方式對服務器資源要求比較高,並發局限於應用中,JDK1.4以前的唯一選擇,但程序直觀簡單易理解。
  • NIO方式適用於連接數目多且連接比較短(輕操作)的架構,比如聊天服務器,並發局限於應用中,編程比較復雜,JDK1.4開始支持。
  • AIO方式使用於連接數目多且連接比較長(重操作)的架構,比如相冊服務器,充分調用OS參與並發操作,編程比較復雜,JDK7開始支持。Netty!

參考:公眾號JavaGuide ,作者Guide哥


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM