作者:rickiyang
出處:www.cnblogs.com/rickiyang/p/11074238.html
我們知道java的I/O模型一共有四種,分別是:傳統的BIO,偽異步I/O,NIO和AIO,
為了澄清概念和分清區別,我們還是先簡單的介紹一下他們的概念,然后再去比較優劣,
1.概念澄清
1.1 BIO
BIO,即Blocking I/O,
網路編程的基本模型是Client/Server 模型,也就是兩個行程之間進行相互通信,其中服務端提供位置資訊(系結的Ip 地址和監聽埠) ,客戶端通過連接操作向服務端監聽的地址發起連接請求,通過三次握手建立連接,如果連接建在成功,雙方就可以通過網路套接字( Socket ) 進行通信,
在基于傳統同步阻塞模型開發中, ServerSocket 負責系結IP 地址,啟動監聽埠:Socket 負責發起連接操作,連接成功之后,雙方通過輸入和輸出流進行同步阻塞式通信,
BIO通信模型圖:

解釋一下上圖:
采用BIO通信模型的服務端,通常由一個獨立的Acceptor執行緒負責監聽客戶端的連接,它接收到客戶端連接請求之后為每個客戶端創建一個新的執行緒進行鏈路處理,處理完成之后,通過輸出流回傳應答給客戶端, 統程銷毀,這就是典型的一請求一回答通信模型,
對于這種IO模型我們知道:用戶執行緒發出IO請求之后,內核會去查看資料是否就緒,如果沒有就緒就會等待資料就緒,而用戶執行緒就會處于阻塞狀態,用戶執行緒交出CPU,當資料就緒之后,內核會將資料拷貝到用戶執行緒,并回傳結果給用戶執行緒,用戶執行緒才解除block狀態,即在讀寫資料程序中會發生阻塞現象,
1.2 偽異步IO
為了解決同步阻塞 I/O 面臨的一個鏈路需要一個執行緒處理的問題,后來有人對它的執行緒模型進行了優化一一后端通過一個執行緒池來處理多個客戶端的請求接入,形成客戶端個數M: 執行緒池最大執行緒數N 的比例關系,其中M 可以遠遠大于N,通過執行緒地可以靈活地調配執行緒資源,設定執行緒的最大值,防止由于海量并發接入導致執行緒耗盡,
偽異步IO通信模型圖:

采用執行緒池和任務佇列可以實作偽異步I/O通信框架,當有新的客戶端接入時,將客戶端的Socket 封裝成一個Task (該任務實作java.lang.
Runnable 介面)投遞到后端的執行緒池中進行處理, JDK 的執行緒將維護一個訊息佇列和N個活躍執行緒, 對訊息佇列中的任務進行處理,
由于統程池可以設定訊息佇列的大小和最大執行緒數,因此,它的資源占用是可控的, 無論多少個客戶端并發訪問, 都不會導致資源的耗盡和省機,
偽異步I/O 通信框架采用了執行緒池實作,因此避免了為每個請求都創建一個獨立執行緒造成的執行緒資源耗盡問題,但是由于它底層的通信依然采用同步阻塞模型,因此無法從根本上解決問題,偽異步I/O 實際上僅僅是對之前I/O 執行緒模型的一個簡單優化,它無法從根本上解決同步I/O 導致的通信執行緒阻塞問題,下面我們就簡單分析下通信對方回傳應答時間過長會引起的級聯故障,
- 服務端處理緩慢,回傳應答訊息耗費60s,平時只需要10ms;
- 采用偽異步I/O 的執行緒在讀取故障服務節點的回應,由于讀/取輸入流是阻塞的,它將會被同步阻塞60s;
- 假如所有的可用執行緒都被故障服務器阻塞,那后續的所有的I/O訊息都將在佇列中排隊;
- 由于執行緒地采用阻塞佇列實作,當佇列積滿之后,后續入佇列的操作將被阻塞;
- 由于前端只有一個Accptor 執行緒接收客戶端接入,它被阻塞在執行緒池的同步阻塞佇列之后,新的客戶端請求訊息將被拒絕,客戶端會發生大量的連接超時;
- 由于幾于所有的連接都超時,呼叫者會認為系統已經崩潰,無法接收新的請求訊息,
如何破解這個難題?下面我們再看一下NIO,
1.3 NIO
NIO,很多人叫他New I/O,由于之前老的I/O 類別庫是阻塞I/O ,New I/O 類別庫的目標就是要讓Java 支持非阻塞I/O,所以,更多的人喜歡稱之為非阻塞I/O(Non-block I/O),
與Socket類和ServerSocket 類相對應, NIO也提供了SocketChannel 和ServerSocketChannel兩種不同的套接字通道實作,這兩種新增的通道都支持阻塞和非阻塞兩種模式,阻塞模式使用非常簡單,但是性能和可靠性都不好,非阻塞模式則正好相反,開發人員可以根據自己的需要來選擇合適的模式,一般來說,低負載、低并發的應用程式可以選擇同步阻塞I/O以降低編程復雜度:對于高負載、高并發的網路應用,需要使用NIO 的非阻塞模式進行開發,
前面我們已經對NIO進行了介紹,我們知道NIO中引入了緩沖區Buffer,通道Channel和多路復用器Selector的概念,一個多路復用器Selector 可以同時輪詢多個Channel,而Channel又是全雙工的,同時支持讀寫操作,使用NIO 編程的優點總結如下:
- 客戶端發起的連接操作是異步的,可以通過在多路復用器注冊OP_CONNECT 等待后續結果,不需要像之前的客戶端那樣被同步阻塞,
- SocketChannel 的讀寫操作都是異步的,如果沒有可讀寫的資料它不會同步等待,直接回傳,這樣I/O 通信執行緒就可以處理其他的鏈路,不需要同步等待這個鏈路可用,
- 執行緒模型的優化:由于JDK 的Selector 在Linux 等主流作業系統上通過epoll 實作,它沒有連接句柄數的限制(只受限于作業系統的最大句柄數或者對單個行程的句柄限制),這意味著一個Selector 執行緒可以同時處理成千上萬個客戶端連接,而且性能不會隨著客戶端的增加而線性下降,因此,它非常適合做高性能、高負載的網路服務器,
1.4 AIO
NIO 2.0 引入了新的異步通道的概念,并提供了異步檔案通道和異步套接字通道的實作,異步通道提供以下兩種方式獲取獲取操作結果:
?通過java.util.concurrent.Future 類來表示異步操作的結果;
?在執行異步操作的時候傳入一個java.nio.channels;
NIO 2.0 的異步套接字通道是真正的異步非阻塞I/O ,對應于UNIX 網路編程中的事件
驅動I/O (AIO) ,它不需要通過多路復用器( Selector) 對注冊的通道進行輪詢操作即可實
現異步讀寫,從而簡化了NIO 的編程模型,
前面對不同的I/O模型進行了簡單介紹,不同的I/O 模型由于執行緒模型、API 等差別很大,所以用法的差異也非常大,我們用一個表格來做一個統一說明:

近期熱文推薦:
1.1,000+ 道 Java面試題及答案整理(2021最新版)
2.終于靠開源專案弄到 IntelliJ IDEA 激活碼了,真香!
3.阿里 Mock 工具正式開源,干掉市面上所有 Mock 工具!
4.Spring Cloud 2020.0.0 正式發布,全新顛覆性版本!
5.《Java開發手冊(嵩山版)》最新發布,速速下載!
覺得不錯,別忘了隨手點贊+轉發哦!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/288258.html
標籤:其他
