最近項目中遇到很多NIO相關知識,以前對這塊接觸得較少,算是個人一個盲區,打算花點時間學習,簡單作一點我的學習總結。java
NIO(New IO)是JDK1.4之後推出的全新IO API,相比傳統IO方式NIO採用了全新的底層I/O模型。傳統IO的設計概念是面向流,而NIO則是面向塊。簡單點說,傳統I/O是基於字節的,全部I/O都被視爲單個字節的移動,使用時需先把對象轉換爲字節碼;而NIO是面向塊的,以塊爲單位處理數據,每一個操做會生成或消費一個塊的數據。從設計理念來看,NIO的操做粒度要比傳統IO大不少,採用這種方式性能有很大提升,但也犧牲了java操做的優雅和簡潔。數組
Java NIO 由如下三個核心模塊組成:緩存
線程的花銷很大,selector幫助開發者突破IO的瓶頸,它提供了單線程處理多個 Channel的機制。若是你的應用打開了多個鏈接(通道),但每一個鏈接的流量都很低,使用Selector就會很方便。數據結構
這是在一個單線程中使用一個Selector處理3個Channel的圖示:架構
要使用Selector,得先向Selector註冊Channel,而後調用它的select()方法。這個方法會一直阻塞到某個註冊的通道有事件就緒。一旦這個方法返回,線程就能夠處理這些事件,事件的例子有如新鏈接進來,數據接收等。app
使用Selector,先得向Selector註冊Channel,而後調用它的select()方法,這個方法會一直阻塞直到某個註冊的通道有事件就緒。一旦這個方法返回,線程就能夠處理這些事件。框架
Channel是一個對象,能夠經過它讀取和寫入數據,全部的IO在NIO中都從一個Channel 開始。Channel中的數據要麼寫入Buffer,要麼從Buffer讀取。拿 NIO 與原來的 I/O 作個比較,Channel就像是流。全部數據都經過Buffer對象來處理,NIO不會將字節直接寫入通道中,相反,它是將數據寫入包含一個或者多個字節的緩衝區。一樣,您不會直接從通道中讀取字節,而是將數據從通道讀入緩衝區,再從緩衝區獲取這個字節。
通道與流的不一樣之處在於通道是雙向的,而流只是在一個方向上移動(一個流必須是 InputStream 或者 OutputStream 的子類), 而 通道能夠用於讀、寫或者同時用於讀寫。所以,通道能夠比流更好地反映底層操做系統的真實狀況。特別是在UNIX模型中,底層操做系統通道是雙向的。性能
經常使用的Channel:單元測試
Buffer與Channel的關係以下圖:學習
Buffer也是NIO的一個亮點,傳統的IO操做面向數據流,意味着每次從流中讀一個或多個字節,直至完成,數據沒有被緩存在任何地方。NIO操做面向緩衝區,數據從Channel讀取到Buffer緩衝區,隨後在Buffer中處理數據。
Buffer其實就是一塊緩存區,內部使用字節數組存儲數據,並維護幾個特殊變量,實現數據的反覆利用。
目前Buffer的實現類有如下幾種:
這些都是抽象類,針對各自的應用場景,下面又有不少子類,功能強大。
通常咱們在工做中遇到NIO相關的場景時,大多都有封裝好的三方庫,但並非說就不必瞭解其實現原理,知其然而不知其因此然用着也會心虛。
另外,學習優秀的開源項目是提高我的能力的一個有效方法,研究源碼能夠從如下幾個點入手(我的認爲):