Buffer的工作方式
1、Buffer的工作方式
前面《java NIO的工作方式》介紹了Selector檢測到通信信道I/O有數據傳輸時,通過select()方法取得SocketChannel,將數據讀取或寫入Buffer緩沖區,下面討論Buffer如何接受和寫出數據。通過查看JDK源碼可知道,Buffer的構造函數
Buffer(int mark, int pos, int lim, int cap) { // package-privateif (cap < 0)throw new IllegalArgumentException();this.capacity = cap;limit(lim);position(pos);if (mark >= 0) {if (mark > pos)throw new IllegalArgumentException();this.mark = mark;}}
Buffer可以簡單的理解為一組基本數據類型的元素列表,它通過幾個變量來保存這個數據的當前位置狀態,也就是四個索引
private int mark = -1;private int position = 0;private int limit;private int capacity;
表1-1 Buffer中的索引及說明
在實際操作數據時他們關系如圖1-2所示。
我們通過ByteBuffer.allocate(11)方法創建一個11個byte的數組緩沖區,初始狀態如圖1-2所示,position的位置為0,capacity和limit默認都是數組長度。當我們寫入5個字節時位置變化如圖1-3所示。
注意:我們查看ByteBuffer.allocate()方法源碼可知,執行的是以下代碼
ByteBuffer(int mark, int pos, int lim, int cap, // package-privatebyte[] hb, int offset){super(mark, pos, lim, cap);this.hb = hb;this.offset = offset;}public static ByteBuffer allocate(int capacity) {if (capacity < 0)throw new IllegalArgumentException();return new HeapByteBuffer(capacity, capacity);}
返回的是HeapByteBuffer又是ByteBuffer的子類,并且在HeapByteBuffer的構造方法中執行的是這樣一個語句:
super(-1, 0, lim, cap, new byte[cap], 0);
也就是說調用的還是ByteBuffer中的構造方法,包范圍內使用。這個方法做了如下工作,首先調用Buffer的構 造方法,依次初始化mark、position、limit、capacity,然后初始化ByteBuffer的屬性byte數組,接著初始 offset,這樣使用allocate方法就可以構造出一個ByteBuffer對象了。
這時我們需要將緩沖區的5個字節數據寫入Channel通信信道,所以我們調用byteBuffer.flip()方法,查看源碼得知
public final Buffer flip() {limit = position;position = 0;mark = -1;return this;}
limit走到position的位置,而position回到了初始位置0,倒轉了緩沖區,數組的狀態發生如圖1-4所示的變化。
這時底層操作系統就可以從緩沖區中正確讀取這5個字節數據并發送出去了。在下一次寫數據之前我們在調一下clear()方法,緩沖區的索引狀態又回到初始位置。
public final Buffer clear() {position = 0;limit = capacity;mark = -1;return this;}
這里還要說明一下mark,當我們調用mark()方法時,它將記錄當前position的前一個位置,當我們調用reset時,position將恢復mark記錄下來的值。還有一點需要說明,通過Channel獲取I/O數據首先要經過操作系統的Socket緩沖區再將數據復制到Buffer中,這個操作系統緩沖區就是底層的TCP協議關聯的RecvQ或SendQ隊列,從操作系統緩沖區到用戶緩沖區復制數據比較耗性能,Buffer提供了另外一種直接操作操作系統緩沖區的方式,即ByteBuffer.allocateDirector(size),
public static ByteBuffer allocateDirect(int capacity) {return new DirectByteBuffer(capacity);}
這個方法返回的DirectorByteBuffer就是與底層存儲空間關聯的緩沖區,它通過Native代碼操作非JVM堆的內存空間。每次創建或者釋放的時候都調用一次System.gc()。注意,在使用DirectorByteBuffer時可能會引起JVM內存泄露問題。DirectByteBuffer和Non-Direct Buffer(HeapByteBuffer)對比如圖1-5所示。
轉載于:https://www.cnblogs.com/wcyBlog/p/4719352.html
總結
以上是生活随笔為你收集整理的Buffer的工作方式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: zip详解
- 下一篇: js 获取URL后面的参数