Java培訓_Java NIO的緩沖區介紹?
NIO的介紹
Java NIO在Java1.4版本的時候就已經存在了的,只不過在當時對于高并發的需求量并沒有現在這么大,所以NIO并沒有引起大家的關注。但是,在現在對于高并發的需求的不大增大,NIO引起了人們的關注,所以在jdk1.7版本的時候,對NIO進行了更新,這一次的更新被人們稱為NIO2。
NIO和傳統IO的區別
那么,NIO和我們傳統的IO有什么區別呢?
區別:
1.傳統IO是面向流的操作,而NIO是面向與緩沖區的
2.IO是阻塞的,NIO是一個非阻塞式的IO
通道和緩沖區
Java NIO系統的核心在于:通道(Channel)和緩沖區(Buffer)。通道表示打開到IO 設備(例如:文件、套接字)的連接。若需要使用NIO 系統,需要獲取用于連接IO 設備的通道以及用于容納數據的緩沖區。然后操作緩沖區,對數據進行處理。
簡單來說就是通道是負責傳輸的,緩沖區是負責存儲的
緩沖區
緩沖區(Buffer):一個用于特定基本數據類型的容器。由java.nio 包定義的,所有緩沖區都是Buffer 抽象類的子類
Java NIO中的Buffer 主要用于與NIO 通道進行交互,數據是從通道讀入緩沖區,從緩沖區寫入通道中的。
Buffer 就像一個數組,可以保存多個相同類型的數據。根據數據類型不同(boolean 除外) ,有以下Buffer 常用子類:
ByteBuffer
CharBuffer
ShortBuffer
IntBuffer
LongBuffer
FloatBuffer
DoubleBuffer
上述Buffer 類他們都采用相似的方法進行管理數據,只是各自管理的數據類型不同而已。都是通過如下方法獲取一個Buffer 對象:
static XxxBuffer allocate(int capacity) : 創建一個容量為capacity 的XxxBuffer 對象
緩沖區的基本屬性
Buffer 中的重要概念:
容量(capacity) :表示Buffer 較大數據容量,緩沖區容量不能為負,并且創建后不能更改。
限制(limit):第一個不應該讀取或寫入的數據的索引,即位于limit 后的數據不可讀寫。緩沖區的限制不能為負,并且不能大于其容量。
位置(position):下一個要讀取或寫入的數據的索引。緩沖區的位置不能為負,并且不能大于其限制
標記(mark)與重置(reset):標記是一個索引,通過Buffer 中的mark() 方法指定Buffer 中一個特定的position,之后可以通過調用reset() 方法恢復到這個position.
緩沖區的數據操作
Buffer 所有子類提供了兩個用于數據操作的方法:get() 與put() 方法
獲取Buffer 中的數據
get() :讀取單個字節
get(byte[] dst):批量讀取多個字節到dst 中
get(int index):讀取指定索引位置的字節(不會移動position)
放入數據到Buffer 中
put(byte b):將給定單個字節寫入緩沖區的當前位置
put(byte[] src):將src 中的字節寫入緩沖區的當前位置
put(int index, byte b):將指定字節寫入緩沖區的索引位置(不會移動position)
直接與非直接緩沖區
字節緩沖區要么是直接的,要么是非直接的。如果為直接字節緩沖區,則Java 虛擬機會盡較大努力直接在此緩沖區上執行本機I/O 操作。也就是說,在每次調用基礎操作系統的一個本機I/O 操作之前(或之后),虛擬機都會盡量避免將緩沖區的內容復制到中間緩沖區中(或從中間緩沖區中復制內容)。
直接字節緩沖區可以通過調用此類的allocateDirect() 工廠方法來創建。此方法返回的緩沖區進行分配和取消分配所需成本通常高于非直接緩沖區。直接緩沖區的內容可以駐留在常規的垃圾回收堆之外,因此,它們對應用程序的內存需求量造成的影響可能并不明顯。所以,建議將直接緩沖區主要分配給那些易受基礎系統的本機I/O 操作影響的大型、持久的緩沖區。一般情況下,最好僅在直接緩沖區能在程序性能方面帶來明顯好處時分配它們。
直接字節緩沖區還可以通過FileChannel 的map() 方法將文件區域直接映射到內存中來創建。該方法返回MappedByteBuffer。Java 平臺的實現有助于通過JNI 從本機代碼創建直接字節緩沖區。如果以上這些緩沖區中的某個緩沖區實例指的是不可訪問的內存區域,則試圖訪問該區域不會更改該緩沖區的內容,并且將會在訪問期間或稍后的某個時間導致拋出不確定的異常。
字節緩沖區是直接緩沖區還是非直接緩沖區可通過調用其isDirect()方法來確定。提供此方法是為了能夠在性能關鍵型代碼中執行顯式緩沖區管理。