NIO、BIO、AIO

https://gitee.com/jly521/NioAio.git  NIO、AIO代碼舉例地址git

  • 從進程級通訊的維度討論時, 阻塞和同步(非阻塞和異步)就是一對同義詞, 且須要針對發送方接收方做區分對待。
    • 發送方阻塞/非阻塞(同步/異步)和接收方的阻塞/非阻塞(同步/異步) 是互不影響的。

#############################個人理解編程

同步和異步(宏觀表現):後端

  • 異步能主動通知你,不用你不停的輪詢
  • 同步的含義是,你是否須要親自去處理數據

阻塞非阻塞(具體實現):緩存

  • 調用不能直接返回結果,所採起的策略(等仍是不等)

BIO(同步阻塞):服務器

  • 好比發起讀入操做,若是獲取不到就會阻塞等待返回結果,整個程序掛起。

NIO(同步非阻塞):網絡

  • channel、selector、buffer
  • 好比發起讀入操做,調用handler
    • 若是獲取不到就會返回讀取不到狀態(好比被鎖),整個程序掛起,過一段時間輪詢好了沒
    • 若是獲取到讀入緩存,開啓讀取動做
  • 使用 select輪詢就是同步

  • 每次從選中的通道讀取數據能夠設置阻塞和非阻塞策略,讀入緩存

AIO,即NIO2.0(異步非阻塞):多線程

  • 好比發起讀入操做,
    • 若是讀取不到,根本不會調用handler
    • 若是獲取到讀入緩存,調用handler處理
  • aio 接收客戶端請求才去的是讀入完成後回調處理函數,因此是異步

  • 建立的AsynchronousSocketChannel通道,名字不難看出是異步通道(非阻塞)

@@@@@@@@@@@@@@@@@@@@@@@@@@架構

IO的方式一般分爲幾種,同步阻塞的BIO、同步非阻塞的NIO、異步非阻塞的AIO。併發

BIO框架

  •  在JDK1.4出來以前,咱們創建網絡鏈接的時候採用BIO模式
  • 須要先在服務端啓動一個ServerSocket,而後在客戶端啓動Socket來對服務端進行通訊,默認狀況下服務端須要對每一個請求創建一堆線程等待請求
  • 而客戶端發送請求後,先諮詢服務端是否有線程相應,若是沒有則會一直等待或者遭到拒絕請求,若是有的話,客戶端會線程會等待請求結束後才繼續執行。

僞異步I/O編程

  • 採用線程池和任務隊列能夠實現一種叫作僞異步的I/O通訊框架。

NIO

  • NIO自己是基於事件驅動思想來完成的,其主要想解決的是BIO的大併發問題: 
  • 將每個客戶端請求分配給一個線程來單獨處理。
    • 操做系統自己也對線程的總數有必定的限制。
    • 若是客戶端的請求過多,服務端程序可能會由於不堪重負而拒絕客戶端的請求,甚至服務器可能會所以而癱瘓。

BIO與NIO一個比較重要的不一樣

  • 是咱們使用BIO的時候每每會引入多線程,每一個鏈接一個單獨的線程;
  • 而NIO則是使用單線程或者只使用少許的多線程,每一個鏈接共用一個線程。

  • NIO的最重要的地方是當一個鏈接建立後,不須要對應一個線程,這個鏈接會被註冊到多路複用器上面
    • 因此全部的鏈接只須要一個線程就能夠搞定,
    • 當這個線程中的多路複用器進行輪詢的時候,發現鏈接上有請求的話,纔開啓一個線程進行處理,也就是一個請求一個線程模式
  • 在NIO的處理方式中,
    • 當一個請求來的話,開啓線程進行處理,可能會等待後端應用的資源(JDBC鏈接等),其實這個線程就被阻塞了,
    • 當併發上來的話,仍是會有BIO同樣的問題。

AIO

  • 與NIO不一樣,當進行讀寫操做時,只須直接調用API的read或write方法便可。
  • 這兩種方法均爲異步的,對於讀操做而言,當有流可讀取時,操做系統會將可讀的流傳入read方法的緩衝區,並通知應用程序;
  • 便可以理解爲,read/write方法都是異步的,完成後會主動調用回調函數。 

彙總圖:

先來個例子理解一下概念,以銀行取款爲例: 

  • 同步 : 本身親自出馬持銀行卡到銀行取錢(使用同步IO時,Java本身處理IO讀寫);
  • 異步 : 委託一小弟拿銀行卡到銀行取錢,而後給你(使用異步IO時,Java將IO讀寫委託給OS處理,須要將數據緩衝區地址和大小傳給OS(銀行卡和密碼),OS須要支持異步IO操做API);
  • 阻塞 : ATM排隊取款,你只能等待(使用阻塞IO時,Java調用會一直阻塞到讀寫完成才返回);
  • 非阻塞 : 使用非阻塞IO時,若是不能讀寫Java調用會立刻返回,當IO事件分發器會通知可讀寫時再繼續進行讀寫,不斷循環直到讀寫完成。

Java對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開始支持。

同步和異步是針對應用程序和內核的交互而言的。 

  • 同步/異步是在時間上強調處理事情的結果/機會成本的兩種處理策略;

阻塞和非阻塞是針對於進程在訪問數據的時候

  • 阻塞方式下讀取或者寫入函數將一直等待,
  • 而非阻塞方式下,讀取或者寫入函數會當即返回一個狀態值。

同步/異步是宏觀上(進程間通信,一般表現爲網絡IO的處理上),

  • 阻塞/非阻塞是微觀上(進程內數據傳輸,一般表現爲對本地IO的處理上);
  • 阻塞和非阻塞是同步/異步的表現形式

相關文章
相關標籤/搜索