bio,nio,aio的區別 select,poll,epoll的區別


先了解一些基本概念,什么是socket?什么是I/O操作
  • unix(like)世界里,一切皆文件,而文件是什么呢?文件就是一串二進制流而已,不管socket,還是FIFO、管道、終端,對我們來說,一切都是文件,一切都是流

  • 在信息交換的過程中,我們都是對這些流進行數據的收發操作,簡稱為I/O操作(input and output)

  • 計算機里有這么多的流,我怎么知道要操作哪個流呢?對,就是文件描述符,即通常所說的fd,一個fd就是一個整數,所以,對這個整數的操作,就是對這個文件(流)的操作。我們創建一個socket,通過系統調用會返回一個文件描述符,那么剩下對socket的操作就會轉化為對這個描述符的操作

然后看看一下幾個概念
  1. BIO:同步阻塞IO,一個客戶端連接,對應一個服務端線程

  2. BIO還有一種變種,偽異步IO,當有新的客戶端接入時,將客戶端的socket封裝成一個task,丟到線程池中處理。優化了后續處理線程的方式

  3. NIO:同步非阻塞IO

  4. AIO:異步非阻塞IO(異步一定是非阻塞)

再看看以下幾個區別
  • 同步和異步針對應用程序來,關注的是程序中間的協作關系

  • 阻塞與非阻塞更關注的是單個進程的執行狀態

再看看I/O處理的過程
  • 數據通過網關到達內核,內核准備好數據

  • 數據從內核緩存寫入用戶緩存

再來講講同步異步就清晰了
  • 同步:不管是BIO,NIO,還是IO多路復用,從內核緩存寫入用戶緩存一定是由 用戶線程自行讀取數據,處理數據

  • 異步:數據是內核寫入的,並放在了用戶線程指定的緩存區,寫入完畢后通知用戶線程

  • 阻塞:數據從網關寫到內核,如果沒寫好,線程就一直在等待

  • 非阻塞:數據總網關寫到內核,用一個線程輪詢的去查看所有的數據是否准備好(I/O多路復用,監聽多個socket)

再來看看I/O多路復用的三種形式
  • select:知道了有I/O事件發生了,卻並不知道是哪那幾個流(可能有一個,多個,甚至全部),我們只能無差別輪詢所有流,找出能讀出數據,或者寫入數據的流,對他們進行操作。所以select具有O(n)的無差別輪詢復雜度,同時處理的流越多,無差別輪詢時間就越長

  • poll:本質上和select沒有區別,它將用戶傳入的數組拷貝到內核空間,然后查詢每個fd對應的設備狀態, 但是它沒有最大連接數的限制,原因是它是基於鏈表來存儲的

  • epoll(Linux內核所特有):可以理解為event poll,不同於忙輪詢和無差別輪詢,epoll會把哪個流發生了怎樣的I/O事件通知我們。所以我們說epoll實際上是事件驅動(每個事件關聯上fd)的,此時我們對這些流的操作都是有意義的。(復雜度降低到了O(1))(Epoll最大的優點就在於它只管你“活躍”的連接,而跟連接總數無關,因此在實際的網絡環境中,Epoll的效率就會遠遠高於select和poll)

  • 注意:表面上看epoll的性能最好,但是在連接數少並且連接都十分活躍的情況下,select和poll的性能可能比epoll好,畢竟epoll的通知機制需要很多函數回調

最后回來看看java內核的NIO的實現
  • 緩沖區Buffer

  1. 緩沖區實際上是一個數組,封裝了對數據結構化訪問以及維護讀寫位置等信息

  2. 在NIO庫中,所有數據都是用緩沖區處理的,在讀取數據時,直接讀取到緩沖區。寫入數據時,直接寫入寫緩沖區。任何時候訪問NIO中的數據,都是 通過緩沖區進行操作

  3. 最常用的的緩沖區是ByteBuffer。大部分Java基本類型都對應一種緩沖區

  • 通道channel

  1. Channel 是一個通道,可以通過它讀取和寫入數據。InputStream和OutputStream各自只能在一個方向上操作

  2. Channel是全雙工的,所以它可以比流更好地映射底層的api

  • 多路復用器Selector

  1. Selector是NIO的編程基礎。多路復用器提供選擇已經就緒的任務的能力

  2. Selector會不斷輪詢注冊在其上的Channel,如果channel上面有了新的TCP連接、讀取或者寫事件,這個channel就是就緒狀態,會被Selector輪詢出來。然后通過SelectionKey集合可以獲取就緒的Channel集合,進行IO操作

  3. 一個Selector可以同時輪詢多個Channel,由於JDK使用了epoll()代替傳統的select實現,所以沒有最大連接句柄1024/2048的限制。這意味着只需要一個線程負責Selector的輪詢,就可以接入成千上萬的客戶端

  • NIO服務端序列圖

     

  • NIO客服端序列圖

  • 簡單版本的交互圖


免責聲明!

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



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