JDK 1.4 中新加入了NIO( New Input/ Output) 類, 引入了一種基於通道和緩衝區的 I/O 方式,它可使用 Native 函數庫直接分配堆外內存,而後經過一個存儲在java
Java堆的 DirectByteBuffer 對象做爲這塊內存的引用進行操做,避免了在 Java 堆和 Native 堆中來回複製數據。NIO 是一種同步非阻塞的 IO 模型。編程
同步是指線程不斷輪詢 IO 事件是否就緒,同步的核心就是 Selector,Selector 代替了線程自己輪詢 IO 事件,避免了阻塞同時減小了沒必要要的線程消耗;數組
非阻塞是指線程在等待 IO 時能夠同時作其餘任務。非阻塞的核心就是通道和緩衝區,當 IO 事件就緒時,可經過寫到緩衝區保證 IO 的成功,無需線程阻塞式地等待。緩存
buffer即爲緩衝區,用於數據存儲,底層用數組存儲,存儲的元素類型爲基本類型,Buffer針對JAVA8個基本數據類型,提供了7個子類型(除了boolean類型)服務器
由於boolean類型能夠經過規定1爲true,0爲false來實現存儲boolean類型,不影響使用,7個子類型最經常使用的是byteBuffer,由於計算機數據傳輸以字節形式;網絡
capacity: 容量位,記錄緩衝區的容量,初始化指定後不可變;框架
limit: 限制位, 用於標記操做位能到達的最大位置,新建一個buffer,limit默認在最後一位,和capacity指向同一個位置;函數
position: 操做位,指向要操做的位置,默認在第零位;post
mark:標記位,用於數據的校驗,在java中mark位默認不啓用,值爲-1;spa
allocate:分配固定大小的buffer流數組;
wrap:動態非陪buffer流數據;
flap:反轉緩衝區,將limit位移到postion位,而後將postion位歸零;
clear: 清空緩衝區,迴歸原始狀態(postion=0, limit = capacity mark = -1);
reset: 重置緩衝區,將postion移動到mark標記位上,防止錯誤;
rewind:重繞緩衝區,將postion歸零,mark置爲-1,用於從新遍歷ByteBuffer流;
使用Buffer讀寫數據通常遵循如下四個步驟:
1. 寫入數據到Buffer
2. 調用flip()
方法將Buffer模式切換到讀模式
3. 從Buffer中讀取數據
4. 調用clear()
方法或者compact()
方法清空緩存區
Channel用於數據傳輸,它是雙向通道,可實現雙向數據傳輸
針對文件:FileChannel
針對UDP:DatagramChannel
針對TCP: SocketChannel、ServerSocketChannel
以下圖(單機版):理論上客戶端能夠收到服務端寫回客戶端的信息「message got」,可是實際上每每獲取不到,主要緣由以下
1. 由於此時客戶端和服務端都是非阻塞,客戶端在發送完信息到服務端後,繼續執行,尚未來得及收到服務端返回的信息,客戶端已經關閉流;
2. 針對第一點,能夠在客戶端在發送完數據到服務端以後,Thread.sleep()來等待服務器端返回信息,此時又面臨一個問題,客戶端在等待的時候,服務端已經關閉流;
3.而上述問題,沒法經過編程來精確實現,由於用戶客戶端發送的數據量未知,基於以上兩點緣由,引出Selector組件;
Selector 選擇器(多路複用器) 用於檢查 Channel的狀態是否處於可讀、可寫,能夠實現單線程管理多個channels,實現管理多個網絡連接;
Netty