java之NIO概念理解

java之NIO概念理解


我們一直都在說傳統的 IO屬於阻塞 IO,而 NIO屬於非阻塞的 IO.

我一直在理解 阻塞 IO 和 非阻塞 IO 的區別。

看了這麼多文章後,今天算是小有所獲,可以用形象的語言來表達他們的區別了。

古人學問無遺力,少壯工夫老始成。


需求背景

我們利用一個需求來進行解釋:服務端需要接收多個客戶端傳輸過來的信息,該流程只包含接收部分,至於接收到的數據是通過線程池進行處理還是怎麼處理,不屬於本章討論範疇,我們只討論幾種不同的IO的接收流程。

阻塞 IO:BIO

傳統的IO是BIO 也稱為同步阻塞 IO。阻塞是體現在哪裡了?

首先給個結論:它會從頭阻塞到尾!

我們通過下圖進行理解:

java之NIO概念理解


一個應用讀取到數據,其實是經過了2個流程。

  1. 數據先是通過網絡填充滿系統內核
  2. 然後從系統內核讀取到應用程序(用戶空間)
上述2個流程很重要,請用心背住並多加理解。


BIO在每一次IO讀取上,會在第一個流程開始到第二個流程結束這個全過程中阻塞。

結合具體的業務來講:客戶端同服務端每建立一個連接進行數據傳輸時,服務端就需要1個線程等待上述進行1和2完成後,才能進行後續收集到的數據的處理任務。

這個過程意味著,服務端需要同N個客戶端進行通信,那麼在服務端就需要N個線程進行監聽。

非阻塞 IO:NIO

NIO 也就是 同步非阻塞 IO,它優化了傳統 IO 在上述流程中的第1步。

這裡的非阻塞指的就是:在第一個流程中,判定系統內核的數據是否可讀上,是非阻塞的,是通過不停輪詢進行判定的。

具體而言如下圖所示:

java之NIO概念理解


異步IO 在第一個流程中,線程會不段的輪詢去獲取系統內核的數據是否就位這個狀態,如果就位了,才能將數據從系統內核拷貝到用戶空間。在第一個流程中,系統是沒有被阻塞的,但是卻是在不停的進行輪詢判定。

這個地方其實我也是有疑問的:非阻塞IO對於阻塞IO而言,非阻塞IO在第一個流程確實是阻塞,但是其卻是隻能通過不停輪詢判定數據是否可讀的狀態。這樣做,性能上有何提升?望有高手能夠解答下這個疑惑!

IO多路複用

IO多路複用是在NIO基礎的改進,Netty就是基於IO多路複用進行數據接收的。

java之NIO概念理解


首先IO多路在不同系統的不同模式下實現是由細微差異的,不過大體的流程一致。

在第一個階段上:

  • 每一個連接都會註冊到系統的 系統內核上。
  • 系統通過某種手段(select\poll\epoll) 判定當前數據是否可讀,當可讀的時候通過callback事件回調的方式,進行後續數據處理。
  • select和poll模型支持的fd有限,且對於fd的掃描是順序掃描,所以高併發下性能不好。
  • Linux下的epoll模型支持更多的fd和基於活躍掃描並回調的方式進行處理,所以高併發下性能更好。

還有一點需要指出:通過IO多路複用,可以1個線程支持多個連接,這個是上述IO模型不具備的。

異步IO:AIO

異步IO是異步非阻塞IO,性能更強大了,全程都是基於callback的。

如下圖所示:

java之NIO概念理解


舉例說明

我們通過一個現實的例子來舉例:我們去銀行辦理業務,需要先填寫業務表單,然後才能進行後續的業務。

傳統的 IO就是:你走到櫃檯後,櫃檯小姐姐盯著你填寫業務表單,後續給你辦理業務。在填寫表單到後續業務處理的過程,櫃檯小姐姐會一直為你服務。這個過程中你填寫業務表達的過程的時候,櫃檯小姐姐就只是盯著你而已,並沒有做什麼工作,存在資源浪費。

多路複用就是:你先到銀行大廳填表,當你填寫完成後你告訴大廳分流的小姐姐我填寫完成了,然後由她給你安排一個操作櫃檯進行後續業務處理。


分享到:


相關文章: