JDK 原始碼學習——ByteBuffer
ByteBuffer 在NIO的作用
Java SE4 開始引入Java NIO,相比較於老的IO,更加依賴底層實現。引入通道(Channels),選擇器(selector),緩衝(Buffers).都更加接近作業系統執行I/O的方式.所以速度更快。
NIO 是非阻塞IO,非阻塞IO的實現是基於事件的,選擇器定義了一個IO通道,程式繼續執行。選擇器上發生事件時,會喚醒選擇器並執行相應動作。IO是阻塞IO,面向流操作,順序讀寫,對於小檔案序列化的讀寫有優勢。nio是面向緩衝器,對資料的偏移支援比較好。
本文提到的ByteBuffer就是緩衝器,一個存放資料的容器,負責與通道進行資料交換。緩衝器總共有ByteBuffer,CharBuffer,DoubleBuffer,FloatBuffer,IntBuffer,LongBuffer,ShortBuffer,除了boolean型別,所有的java基本型別都有buffer實現
ByteBuffer的重要屬性
Buffer 基類
屬性
緩衝器都繼承了Buffer類,Buffer是一個固定大小的資料容器。除了儲存內容之外,還有三個重要的屬性。
capacity buffer中元素總數
position 寫模式下就是下一個元素的index,讀模式就是當前元素index
limit 是不應該被讀/寫的第一個元素index。寫模式時就是capacity,讀模式則是下一個元素的index.如下圖:圖片來自http://javapapers.com/java/java-nio-buffer/
方法
- flip
一般是切換到讀操作。或者是為寫操作準備一個新的序列
public final Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
eg.重複向一個ByteBuffer寫資料的時候,賦值完畢,必須要flip.開始一個新的新序列,否則position會等於limit,返回空值
public static void main(String[] args) {
byte[] bytes1=new byte[]{1, 6, 3};
ByteBuffer buffer =fromByteArray(bytes1);
System.out.println(buffer);
byte [] bytes2 =new byte[]{1,2,3};
ByteBuffer buffer2=fromByteArray(bytes2);
System.out.println(buffer2);
}
/**
* If you are building up a ByteBuffer by repeatedly writing into it, and then want to give it away, you must remember to flip() it.
* If we did not flip() it, the returned ByteBuffer would be empty because the position would be equal to the limit.
* @param bytes
* @return
*/
public static ByteBuffer fromByteArray(byte[] bytes) {
final ByteBuffer ret = ByteBuffer.wrap(new byte[bytes.length]);
ret.put(bytes);
ret.flip();
return ret;
}
- rewind
rewind倒回,將position 設定為0,重新讀取
public final Buffer rewind() {
position = 0;
mark = -1;
return this;
}
- clear
clear 並沒有真正的清除資料,將position設定為0,limit設定為capacity.
public final Buffer clear() {
position = 0;
limit = capacity;
mark = -1;
return this;
}
ByteBuffer
ByteBuffer 相比較其他的緩衝器有些區別
可以分配直接緩衝區
直接緩衝區,JVM會盡可能的直接在此緩衝區執行本機IO操作。避免與中間緩衝區互動可以通過mapping將檔案區域直接對映到記憶體來建立、
訪問二進位制資料