圖解bytebuffer

  1. 因何而寫

    網上關於bytebuffer的文章真的不少,爲什麼在此還要寫一篇呢?主要是基於如下幾點考慮
    1. 不少人在使用t-io時,還不會bytebuffer,只會照着t-io提供的例子照貓畫虎,不利於靈活運用
    2. 網上搜到的一些相關文章,講得不是太易懂,不利於初學者靈活運用bytebuffer
    3. 本文旨在講解靈活運用bytebuffer所需的最小知識,以幫助用戶快速掌握bytebuffer
  2. 用極易的方式認識一下bytebuffer

    1. bytebuffer之第一眼印象

      咱們能夠把bytebuffer理解成以下幾個成員組成的一個新對象,對,就是一個普通的java對象,像string同樣的java對象。(強調一下,這裏只是說這樣理解,實際上有些bytebuffer的實現類並不是這樣實現,而且這裏只列出掌握bytebuffer所須要的最小知識集合,其它諸如mark等字段本文並不介紹,以避免增長初學者的惑度
      1. byte[] bytes: 用來存儲數據
      2. int capacity: 用來表示bytes的容量,那麼能夠想像capacity就等於bytes.size(),此值在初始化bytes後,是不可變的。
      3. int limit: 用來表示bytes實際裝了多少數據,能夠容易想像獲得limit <= capacity,此值是可靈活變更的
      4. int position: 用來表示在哪一個位置開始往bytes寫數據或是讀數據,此值是可靈活變更的
      經過下圖,對bytebuffer造成一個感觀認識吧
    2. bytebuffer之經常使用操做及各操做對內部變量帶來的變化

      1. 建立bytebuffer: ByteBuffer.allocate(6)

      2. 寫入一個字節: byteBuffer.put((byte)3)

      3. 讀取一個字節: byte bs = byteBuffer.get()

        對於剛剛寫好的bytebuffer,咱們要讀取它的內容,須要先設置一下position和limit,不然讀的位置就不對
        byteBuffer.position(0);  //設置position到0位置,這樣讀數據時就從這個位置開始讀
        byteBuffer.limit(1);     //設置limit爲1,表示當前bytebuffer的有效數據長度是1
        咱們看一下,設置position和limit後,bytebuffer的內部變化

        接下來,咱們就能夠讀取剛纔寫入的數據了
        byte bs = byteBuffer.get();

    3. bytebuffer之使用心得

      這裏說的是做者本人使用bytebuffer的一些心得,這些與其說是心得,不如說是實踐+測試得來的一些經驗,因此並不保證就是權威的,歡迎有更深研究的朋友來合理討論,若是有不一樣意見,能夠以更好的論據來講服對方。
      1. 合理靈活運用HeapByteBuffer.array()

        HeapByteBuffer.array()返回的是其內部byte[],咱們拿到這個後,就能夠隨意對這個byte[]隨便操做了,能夠參考t-io的SendRunnable.java的下面這段代碼
        ByteBuffer allByteBuffer = ByteBuffer.allocate(allBytebufferCapacity);
        byte[] dest = allByteBuffer.array();
        for (ByteBuffer byteBuffer : byteBuffers) {
        	if (byteBuffer != null) {
        		int length = byteBuffer.limit();
        		int position = allByteBuffer.position();
        		System.arraycopy(byteBuffer.array(), 0, dest, position, length);
        		allByteBuffer.position(position + length);
        	}
        }
        注意:DirectBuffer內部是沒有byte[]的,也就沒有所謂的byte[]操做了。
      2. jdk自帶的bytebuffer已經足夠好用

        有一些nio/aio框架喜歡本身弄一套bytebuffer來,既增長了做者本身的工做量,又增長了用戶的學習成本,但咱們要知道一點,nio/aio在發送數據時,最終的參數是jdk的bytebuffer,咱們真的有必要再做一次轉換和計算嗎?儘管某些中間過程是「零拷貝」(這個「零拷貝」也是有額外的計算成本的)的,可是jdk版bytebuffer的誕生到發送完畢,這整個過程經歷了哪些操做呢?真的是如某書某博客上所說的「零拷貝」嗎?更不該該把某些對象池的作法也牽強附會到「零拷貝」的概念中來----對象池屬對象重複利用範疇,既然是重複利用天然便已經默認有零拷貝的屬性了,可是對象池自己的維護也是須要消耗資源的,因此並非全部場景說用了對象池,性能就提高了,有時候用很差反而增長負擔,因此萬事要以測試數據爲準,不該盲目人云亦云!
  3. 最後附上bytebuffer的示例程序

    這裏附上bytebuffer的示例程序,用戶能夠本身debug觀察觀察,增長bytebuffer的相關概念,以便更靈活的運用bytebuffer
  4. import java.nio.ByteBuffer;
    
    /**
     * @author tanyaowu 
     * 2017年5月1日 上午9:00:50
     */
    public class Ts {
    
    	/**
    	 * 
    	 * @author: tanyaowu
    	 */
    	public Ts() {
    	}
    
    	/**
    	 * @param args
    	 * @author: tanyaowu
    	 */
    	public static void main(String[] args) {
    		ByteBuffer byteBuffer = ByteBuffer.allocate(6);
    		byteBuffer.put((byte)3);
    		
    		byteBuffer.position(0);  //設置position到0位置,這樣讀數據時就從這個位置開始讀
    		byteBuffer.limit(1);     //設置limit爲1,表示當前bytebuffer的有效數據長度是1
    		
    		byte bs = byteBuffer.get();
    		System.out.println(byteBuffer);
    	}
    }
相關文章
相關標籤/搜索