JAVA NIO學習筆記1 - 架構簡介


最近項目中遇到不少NIO相關知識,之前對這塊接觸得較少,算是我的一個盲區,打算花點時間學習,簡單做一點個人學習總結。

簡介

NIO(New IO)是JDK1.4以后推出的全新IO API,相比傳統IO方式NIO采用了全新的底層I/O模型。傳統IO的設計概念是面向流,而NIO則是面向塊。簡單點說,傳統I/O是基於字節的,所有I/O都被視為單個字節的移動,使用時需先把對象轉換為字節碼;而NIO是面向塊的,以塊為單位處理數據,每個操作會生成或消費一個塊的數據。從設計理念來看,NIO的操作粒度要比傳統IO大很多,采用這種方式性能有很大提高,但也犧牲了java操作的優雅和簡潔。

核心模塊

Java NIO 由以下三個核心模塊組成:

  • Selector
  • Channel
  • Buffer

selector_2016_10_29_2_17_48_shanbiao_jsb

Selector

線程的花銷很大,selector幫助開發者突破IO的瓶頸,它提供了單線程處理多個 Channel的機制。如果你的應用打開了多個連接(通道),但每個連接的流量都很低,使用Selector就會很方便。

這是在一個單線程中使用一個Selector處理3個Channel的圖示:

overview_selectors

要使用Selector,得先向Selector注冊Channel,然后調用它的select()方法。這個方法會一直阻塞到某個注冊的通道有事件就緒。一旦這個方法返回,線程就可以處理這些事件,事件的例子有如新連接進來,數據接收等。

使用Selector,先得向Selector注冊Channel,然后調用它的select()方法,這個方法會一直阻塞直到某個注冊的通道有事件就緒。一旦這個方法返回,線程就可以處理這些事件。

Channel

Channel是一個對象,可以通過它讀取和寫入數據,所有的IO在NIO中都從一個Channel 開始。Channel中的數據要么寫入Buffer,要么從Buffer讀取。拿 NIO 與原來的 I/O 做個比較,Channel就像是流。所有數據都通過Buffer對象來處理,NIO不會將字節直接寫入通道中,相反,它是將數據寫入包含一個或者多個字節的緩沖區。同樣,您不會直接從通道中讀取字節,而是將數據從通道讀入緩沖區,再從緩沖區獲取這個字節。
通道與流的不同之處在於通道是雙向的,而流只是在一個方向上移動(一個流必須是 InputStream 或者 OutputStream 的子類), 而 通道可以用於讀、寫或者同時用於讀寫。因此,通道可以比流更好地反映底層操作系統的真實情況。特別是在UNIX模型中,底層操作系統通道是雙向的。

常用的Channel:

  • FileChannel:File
  • DatagramChannel:UDP
  • ScoketChannel:TCP
  • ServerSocketChannel:監聽TCP連接

Buffer

Buffer與Channel的關系如下圖:

scatter

Buffer也是NIO的一個亮點,傳統的IO操作面向數據流,意味着每次從流中讀一個或多個字節,直至完成,數據沒有被緩存在任何地方。NIO操作面向緩沖區,數據從Channel讀取到Buffer緩沖區,隨后在Buffer中處理數據。

Buffer其實就是一塊緩存區,內部使用字節數組存儲數據,並維護幾個特殊變量,實現數據的反復利用。

目前Buffer的實現類有以下幾種:

  • ByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer
  • MappedByteBuffer

這些都是抽象類,針對各自的應用場景,下面又有很多子類,功能強大。

思考總結

一般我們在工作中遇到NIO相關的場景時,大多都有封裝好的三方庫,但並不是說就沒必要了解其實現原理,知其然而不知其所以然用着也會心虛。

另外,學習優秀的開源項目是提升個人能力的一個有效方法,研究源碼可以從以下幾個點入手(個人認為):

    • 架構文檔 (在腦中建立框架圖)
    • 示例代碼與單元測試(知道具體接口使用細節)
    • 具體模塊實現代碼(數據結構 - public方法 - private方法)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM