最近大概看了ZooKeeper和Mina的源碼發現都是用Java NIO實現的,因此有必要搞清楚什麼是NIO。下面是我結合網絡資料本身總結的,爲了節約時間圖示隨便畫的,能達意就行。java
簡介:編程
BIO:同步阻塞式IO,服務器實現模式爲一個鏈接一個線程,即客戶端有鏈接請求時服務器端就須要啓動一個線程進行處理,若是這個鏈接不作任何事情會形成沒必要要的線程開銷,固然能夠經過線程池機制改善。
NIO:同步非阻塞式IO,服務器實現模式爲一個請求一個線程,即客戶端發送的鏈接請求都會註冊到多路複用器上,多路複用器輪詢到鏈接有I/O請求時才啓動一個線程進行處理。
AIO(NIO.2):異步非阻塞式IO,服務器實現模式爲一個有效請求一個線程,客戶端的I/O請求都是由OS先完成了再通知服務器應用去啓動線程進行處理。
BIO
同步阻塞式IO,相信每個學習過操做系統網絡編程或者任何語言的網絡編程的人都很熟悉,在while循環中服務端會調用accept方法等待接收客戶端的鏈接請求,一旦接收到一個鏈接請求,就能夠創建通訊套接字在這個通訊套接字上進行讀寫操做,此時不能再接收其餘客戶端鏈接請求,只能等待同當前鏈接的客戶端的操做執行完成。
若是BIO要可以同時處理多個客戶端請求,就必須使用多線程,即每次accept阻塞等待來自客戶端請求,一旦受到鏈接請求就創建通訊套接字同時開啓一個新的線程來處理這個套接字的數據讀寫請求,而後馬上又繼續accept等待其餘客戶端鏈接請求,即爲每個客戶端鏈接請求都建立一個線程來單獨處理,大概原理圖就像這樣:
雖然此時服務器具有了高併發能力,即可以同時處理多個客戶端請求了,可是卻帶來了一個問題,隨着開啓的線程數目增多,將會消耗過多的內存資源,致使服務器變慢甚至崩潰,NIO能夠必定程度解決這個問題。服務器
NIO
同步非阻塞式IO,關鍵是採用了事件驅動的思想來實現了一個多路轉換器。
NIO與BIO最大的區別就是隻須要開啓一個線程就能夠處理來自多個客戶端的IO事件,這是怎麼作到的呢?
就是多路複用器,能夠監聽來自多個客戶端的IO事件:
A. 若服務端監聽到客戶端鏈接請求,便爲其創建通訊套接字(java中就是通道),而後返回繼續監聽,若同時有多個客戶端鏈接請求到來也能夠所有收到,依次爲它們都創建通訊套接字。
B. 若服務端監聽到來自已經建立了通訊套接字的客戶端發送來的數據,就會調用對應接口處理接收到的數據,若同時有多個客戶端發來數據也能夠依次進行處理。
C. 監聽多個客戶端的鏈接請求和接收數據請求同時還能監聽本身時候有數據要發送。
總之就是在一個線程中就能夠調用多路複用接口(java中是select)阻塞同時監聽來自多個客戶端的IO請求,一旦有收到IO請求就調用對應函數處理。
各自應用場景
到這裏你也許已經發現,一旦有請求到來(不論是幾個同時到仍是隻有一個到),都會調用對應IO處理函數處理,因此:網絡
(1)NIO適合處理鏈接數目特別多,可是鏈接比較短(輕操做)的場景,Jetty,Mina,ZooKeeper等都是基於java nio實現。多線程
(2)BIO方式適用於鏈接數目比較小且固定的場景,這種方式對服務器資源要求比較高,併發侷限於應用中。併發
(3)AIO新的IO2.0,即NIO2.0,jdk1.7開始應用,叫作異步不阻塞的IO。AIO引入異常通道的概念,採用了Proactor模式,簡化了程序編寫,一個有效的請求才啓動一個線程,它的特色是先由操做系統完成後才通知服務端程序啓動線程去處理,通常適用於鏈接數較多且鏈接時間長的應用。異步
附錄:下面附上一個別人寫的java NIO的例子。
服務端:
客戶端:
轉載自:https://www.cnblogs.com/zedosu/p/6666984.html