Java BIO、NIO、AIO

同步與異步

同步與異步的概念, 關注的是 消息通訊機制數組

  • 同步是指發出一個請求, 在沒有獲得結果以前該請求就不返回結果, 請求返回時, 也就獲得結果了.

好比洗衣服, 把衣服放在洗衣機裏, 沒有洗好以前咱們一直看着, 直到洗好了纔拿出來晾曬.網絡

  • 異步是指發出一個請求後, 馬上獲得了迴應, 但沒有返回結果. 這時咱們能夠再處理別的事情(發送其餘請求), 因此這種方式須要咱們經過狀態主動查看是否有告終果, 或者能夠設置一個回調來通知調用者.

好比洗衣服時, 把衣服放到洗衣機裏, 咱們就能夠去作別的事情, 過會兒來看看有沒有洗好(經過狀態查詢); 
或者咱們設置洗衣機洗完後響鈴來通知咱們洗好了(回調通知)異步


阻塞與非阻塞

阻塞與非阻塞很容易和同步與異步混淆, 但二者關注點是不同的. 阻塞與非阻塞關注的是 程序在等待調用結果時的狀態socket

  • 阻塞是指請求結果返回以前, 當前線程會被掛起(被阻塞), 這時線程什麼也作不了
  • 非阻塞是指請求結果返回以前, 當前線程沒有被阻塞, 仍然能夠作其餘事情.

阻塞有個明顯的特徵就是線程一般是處於BLOCKED狀態(BIO中的read()操做時, 線程阻塞是JVM配合OS完成的, 此時Java獲取到線程的狀態還是RUNNABLE但它確實已經被阻塞了)函數

若是要拿同步來作比較的話, 同步通訊方式中的線程在發送請求以後等待結果這個過程當中應該處於RUNNABLE狀態, 同步必須一步一步來完成, 就像是代碼必須執行完一行才能執行下一行, 因此必須等待這個請求返回以後纔可進行下一個請求, 即便等待結果的時間長, 也是在執行這個請求的過程當中. 而異步則不用等上一條執行完, 能夠先執行別的代碼, 等請求有告終果再來獲取結果.操作系統


IO模型

Java中的IO操做是JVM配合操做系統來完成的. 對於一個IO的讀操做, 數據會先被拷貝到操做系統內核的緩衝區中, 而後從操做系統內核的緩衝區拷貝到應用程序的地址空間. 因此整個過程可分爲兩個階段:線程

  1. 等待I/O數據準備好. 這取決於IO目標返回數據的速度, 如網絡IO時看網速和數據自己的大小.
  2. 數據從內核緩衝區拷貝到進程內.

根據這兩個階段, 產生了常見的幾種不一樣的IO模型: BIONIOIO多路複用AIO.code

BIO

BIOBlocking I/O(阻塞 I/O), BIO整個過程以下圖:接口

BIO

程序發送請求給內核, 而後由內核去進行通訊, 在內核準備好數據以前這個線程是被掛起的, 因此在兩個階段程序都處於掛起狀態.進程

  • BIO的特色就是在IO執行的兩個階段都被block了

NIO

NIONon-Blocking I/O(非阻塞 I/O), NIO整個過程以下圖:

NIO

與BIO的明顯區別是, 發起第一次請求後, 線程並無被阻塞, 它反覆檢查數據是否準備好, 把原來大塊不能用的阻塞時間分紅了許多」小阻塞」(檢查), 因此進程不斷有機會被執行. 這個檢查有沒有準備好數據的過程有點相似於」輪詢」.

  • NIO的特色就是程序須要不斷的主動詢問內核數據是否準備好。第一個階段非阻塞, 第二個階段阻塞

IO多路複用

IO多路複用(I/O Multiplexing)有selectpollepoll等不一樣方式, 它的優勢在於單個線程能夠同時處理多個網絡IO.

NIO中輪詢操做是用戶線程進行的, 若是把這個任務交給其餘線程, 則用戶線程就不用這麼費勁的查詢狀態了. IO多路複用調用系統級別的selectpoll模型, 由系統進行監控IO狀態. select輪詢能夠監控許多socket的IO請求, 當有一個socket的數據準備好時就能夠返回.

  • select: 註冊事件由數組管理, 數組是有長度的, 32位機上限1024, 64位機上限2048. 輪詢查找時須要遍歷數組.
  • poll: 把select的數組採用鏈表實現, 所以沒了最大數量的限制
  • epoll方式: 基於事件回調機制, 回調時直接通知進程, 無須使用某種方式來查看狀態.

多路複用IO過程圖:

Multiplexing_IO

用戶線程有一段時間是阻塞的, 從上圖來看, 與NIO很像, 但與NIO不同的是, select不是等到全部數據準備好才返回, 而是隻要有一個準備好就返回, 它的優點在於能夠同時處理多個鏈接. 若鏈接不是不少的話, 它的效率不必定高, 可能還會更差.

Java 1.4開始支持NIO(New IO), 就是採用了這種方式, 在套接字上提供selector選擇機制, 當發起select()時會阻塞等待至少一個事件返回.

  • 多路複用IO的特色是用戶進程能同時等待多個IO請求, 系統來監控IO狀態, 其中的任意一個進入讀就緒狀態, select函數就能夠返回.

AIO

AIOAsynchronous I/O(異步 I/O), 這是Java 1.7引入的NIO 2.0中用到的. 整個過程當中, 用戶線程發起一個系統調用以後無須等待, 能夠處理別的事情. 由操做系統等待接收內容, 接收後把數據拷貝到用戶進程中, 最後通知用戶程序已經可使用數據了, 兩個階段都是非阻塞的. AIO整個過程以下圖:

AIO

AIO屬於異步模型, 用戶線程能夠同時處理別的事情, 咱們怎麼進一步加工處理結果呢? Java在這個模型中提供了兩種方法:

  1. 一種是基於」回調」, 咱們能夠實現CompletionHandler接口, 在調用時把回調函數傳遞給對應的API便可
  2. 另外一種是返回一個Future. 處理完別的事情, 能夠經過isDone()可查看是否已經準備好數據, 經過get()方法等待返回數據.

小結

上面這幾種模式, BIO整個過程都等待返回, NIOIO多路複用在第二個階段等待返回, 所以從整個過程來看, 這三個模式都屬於同步方式. AIO在整個過程當中沒有等待返回, 屬於異步方式.

相關文章
相關標籤/搜索