天天看點

android bytebuffer 大小,ByteBuffer小結

前言

在閱讀源碼的過程中,發現比較多的使用到了bytebuffer,但是由于之前沒有接觸過,是以現做以總結,以備複習。

ByteBuffer類位于java.nio包下,所謂nio:代表new io,另一種解釋:N代表Non-blocking IO,非阻塞的IO。其中差別如下:

Java NIO和IO的主要差別

android bytebuffer 大小,ByteBuffer小結

表格簡單差別

面向流和緩沖型

Java NIO和IO第一個大的不同點是IO是面向流的,NIO則是緩沖型的。那麼,這到底是什麼意思?

Java IO是面向流的意味着我們從一個流中一次讀取一個或多個位元組。而要對讀到的位元組作何處理由我們自己決定;這其中沒有任何緩存。此外,我們不能在資料流中來回移動;如果想要在從流讀取的資料中來回移動,我們需要首先将資料緩存到緩沖區。

Java NIO的緩沖型方法稍有不同。資料讀取到緩沖區後被加工,我們可以根據需求在資料中來回移動。這為處理提供了靈活性;然而為了充分處理所有資料我們還需要檢查緩沖區是否包含所有需要的資料,并且我們需要確定讀取更多資料到緩沖區時未被處理的資料不能被覆寫。

阻塞型IO和非阻塞型IO

Java IO的各種流是阻塞型的。這意味着,當一個線程調用read()方法或write()方法時這個線程将一直被阻塞,直到有資料被讀到或者資料被完全寫入;在被阻塞的同時,該線程不能做任何其他事情。

Java NIO的非阻塞模式允許一個線程從一個channel中請求讀取資料,這隻會取到目前有效的資料或目前沒有資料有效時擷取不到任何資料;而不是一直阻塞直到所讀取資料準備好為止;在這同時該線程可以做其他事情。

這個過程對非阻塞式資料寫入也是成立的。一個線程可以寫入一些資料到channel,但是不用等待資料被完全寫入。該線程在請求完成後可以繼續同時去做其他事情。

當線程不在IO調用上被阻塞時,那麼它們的空閑時間通常都花在了在其他channel上執行IO操作。也就是說,一個線程可以管理多個輸入和輸出的channel。

選擇器(Selectors)

Java NIO中的selector允許一個線程監視多個channel的輸入。我們可以在一個selector上注冊多個channel,然後使用一個線程來 “選擇”輸入可用的channel來處理,或者選擇準備好寫入的channel。這種選擇器模式使單個線程管理多個channel變的非常容易。

NIO和IO對應用設計的影響

不論我們選擇NIO還是IO作為我們的IO工具包都可能在以下幾方面影響應用的設計:

NIO或IO API類的調用

資料的處理

用于處理資料的線程數量

bytebuffer 使用

關于buffer的若幹點

buffer是一個面向特定原始資料類型的容器;

包含三個屬性:capacity,limit和position,分别對應的是:緩存的容量,讀取資料的限制和讀取資料的位置;

capacity:配置設定好的記憶體塊大小,配置設定好後大小不可修改;

limit:在讀模式下,表示緩存的内資料大小;寫模式下,表示最多可以存入資料大小,此時和capacity值相等;

position:表示讀寫的位置,下表從0開始;

making和resetting:對應标記和恢複;

0 <= mark <= position <= limit <= capacity

clear(),flip(),rewind()方法:

clear:重新寫入資料使用,将目前可用的第一個位置指向了buffer的首位值;

flip:用于讀取buffer中的資料,将position置為0;

rewind:limit不變,position =0 ,指向了第一個位置處,用于重新讀取;

hasRemaining()和remaining()

hasRemaining() ---是否還有可用的空間

remaining() ----檢視還有多少可用的空間

常用API

allocate(int capacity): 配置設定一個新的位元組緩沖區

get():相對 get 方法

get(int index) : 絕對 get 方法

getInt(): 用于讀取 int 值的相對 get 方法

put(byte b): 相對 put 方法(可選操作)

代碼示範

讀取位元組

public class TestBuffer {

public static void main(String[] args) throws Exception {

ByteBuffer bb = ByteBuffer.allocate(48);

String str = "ceshiwenjianneirong...";

byte[] tmp = str.getBytes();

System.out.println(bb.toString());

bb.put(tmp);

// 從寫模式切換到讀模式

bb.flip();

System.out.println(bb.toString());

System.out.println((char)bb.get() + "===");

}

}

讀取整形

public class TestBuffer {

public static void main(String[] args) throws Exception {

ByteBuffer bb = ByteBuffer.allocate(48);

System.out.println(bb.toString());

bb.putInt(12345645);

// 從寫模式切換到讀模式

bb.flip();

System.out.println(bb.toString());

System.out.println(bb.getInt() + "===");

}

}

代碼說明:

bb.toString():toString() : 傳回彙總了此緩沖區狀态的字元串。

輸出結果:

java.nio.HeapByteBuffer[pos=0 lim=48 cap=48]

java.nio.HeapByteBuffer[pos=0 lim=4 cap=48]

12345645===