最近在作通訊和傳輸的項目,大量的使用NIO和Mina,雖然以前一直對這部分比較關注,可是尚未好好的總結一下這方面的內容。今天想寫點兒NIO裏最基本的一個類ByteBuffer。至於Mina中的IoBuffer,咱們能夠先看Mina API中的描述: java
A byte buffer used by MINA applications. This is a replacement for ByteBuffer. Please refer to ByteBuffer documentation for preliminary usage。 app
固然,接下去也有寫到:MINA does not use NIO ByteBuffer directly for two reasons,至於這Two Reasons,咱們將在後面的比較中展開。 dom
ByteBuffer繼承了Buffer,對Buffer的理解能夠說是NIO的入門。在Buffer中有4個重要的Attributes: ide
Capacity: the capacity is set when the buffer is created and can never be changed。 spa
Limit: the first element of the buffer that should not be read or written 翻譯
Position: the index of the next element to be read or written code
Mark: a remembered position. Calling mark() set mark=position 繼承
他們的關係以下:0<=mark<=position<=limit<=capacity。 ip
通俗的講: 內存
Capacity:開的內存的大小,一旦設定了,就不能更改了。注意,這裏指的是原生的NIO。
Limit:能夠分讀寫來統計。在寫入buffer時,limit表示有多少空間能夠寫入。在從buffer寫出時,limit表示有多少能夠寫出。
Position:下一個要被讀或寫的位置。
Mark:標記位,能夠記住某個position,方便後續操做。
對於ByteBuffer有以下經常使用的操做:
flip()::讀寫模式的轉換。
rewind() :將 position 重置爲 0 ,通常用於重複讀。
clear() :清空 buffer ,準備再次被寫入 (position 變成 0 , limit 變成 capacity) 。
compact(): 將未讀取的數據拷貝到 buffer 的頭部位。
mark() 、 reset():mark 能夠標記一個位置, reset 能夠重置到該位置。
get()、getShort()等一系列get操做:獲取ByteBuffer中的內容,固然這裏get的內容都是從position開始的,因此要時刻注意position。每次get以後position都會改變。Position的變化是根據你get的類型,若是是short,那就是2個byte,若是是int,那就是增長4個byte,即32。
put()、putShort()等一系列put操做:向ByteBuffer添加內容,這裏put的內容都是從position開始的。每次put以後position都會改變。
固然還有allocate、hasRemaining等經常使用的方法,不過這些用法通常都不會出錯,使用起來和4個attributes也沒有多大相關。特別注意:Buffers are not thread-safe. If you want to access a given buffer concurrently from multiple threads, you will need to do your own synchronization prior to accessing the buffer.至於Buffer或者ByteBuffer有什麼用?那太多了,只要涉及到傳輸、涉及到通訊,均可以用到。固然你也能夠用它最原始的含義,緩衝。
好了NIO的ByteBuffer告一段落,接下來先說IoBuffer中說不用ByteBuffer的Two Reasons:
l It doesn't provide useful getters and putters such as fill, get/putString, and get/putAsciiInt() enough.
l It is difficult to write variable-length data due to its fixed capacity
看好了,對於第一點我想也沒什麼,增長了更實用的getString。關鍵是第二點,IoBuffer實現了Auto Expand和Auto Shrink。這就意味了,capacity能夠根據傳輸內容的大小自動變動了。在使用上,咱們能夠這樣寫:
IoBuffer buf = IoBuffer.allocate(1024).setAutoExpand(true);在 IoBuffer的源碼中,大部分都使用了原生的 ByteBuffer來實現,這部分採用 allocator來實現。
/** The allocator used to create new buffers */ private static IoBufferAllocator allocator = new SimpleBufferAllocator();在SimpleBufferAllocator的其中一段allocate:
public ByteBuffer allocateNioBuffer(int capacity, boolean direct) { ByteBuffer nioBuffer; if (direct) { nioBuffer = ByteBuffer.allocateDirect(capacity); } else { nioBuffer = ByteBuffer.allocate(capacity); } return nioBuffer; }至於其餘操做,和 ByteBuffer 相似。
貼一段Reilly - Java NIO中的一段代碼做爲結束,後續更多的Mina相關會根據開發進度給出介紹:
import java.nio.CharBuffer; public class BufferFillDrain { private static int index = 0; private static String[] strings = { "A random string value", "The product of an infinite number of monkeys", "Hey hey we're the Monkees" }; private static boolean fillBuffer(CharBuffer buffer) { if (index >= strings.length) { return false; } String string = strings[index++]; for (int i = 0; i < string.length(); i++) { buffer.put(string.charAt(i)); } return true; } private static void drainBuffer(CharBuffer buffer){ while(buffer.hasRemaining()){ System.out.println(buffer.get()); } System.err.println(""); } public static void main(String[] args) { CharBuffer buffer=CharBuffer.allocate(100); while(fillBuffer(buffer)){ buffer.flip(); drainBuffer(buffer); buffer.clear(); } } }由於以前作筆記的時候用的都是英文,因此好多都沒有翻譯過來,更好的文檔是官方的文檔,謝謝觀賞。