1. 程式人生 > >Mina Core 08-IoBuffer

Mina Core 08-IoBuffer

MINA應用程式使用的位元組緩衝區。

    這是ByteBuffer的替代品。 MINA不直接使用NIO ByteBuffer有兩個原因:

  1. 它不提供有用的getter和putter,如fill,get / putString和get / putAsciiInt()。
  2. 由於其固定容量,很難編寫可變長度資料

注意:

這將在MINA 3中發生變化.MINA在nio ByteBuffer之上擁有自己的包裝器的主要原因是具有可擴充套件的緩衝區。這是一個非常糟糕的決定。緩衝區只是緩衝區:在使用之前臨時儲存臨時資料的地方。存在許多其他解決方案,例如定義依賴於NIO ByteBuffers列表的包裝器,而不是僅僅因為我們想要擴充套件緩衝區容量而將現有緩衝區複製到更大的緩衝區。

在過濾器中使用InputStream而不是位元組緩衝區也可能更為舒適,因為它並不意味著儲存資料的性質:它可以是位元組陣列,字串,訊息......

最後,並非最不重要的是,當前的實現擊敗了一個目標:零拷貝策略(即,一旦我們從套接字讀取資料,我們希望避免稍後複製)。當我們使用可擴充套件位元組緩衝區時,如果我們必須管理大訊息,我們肯定會複製這些資料。假設MINA ByteBuffer只是NIO ByteBuffer之上的包裝器,使用直接緩衝區時這可能是一個真正的問題。

IoBuffer操作

分配新的緩衝區

IoBuffer是一個抽象類,因此無法直接例項化。要分配IoBuffer,我們需要使用兩個allocate()方法之一。

// Allocates a new buffer with a specific size, defining its type (direct or heap)

public static IoBuffer allocate(int capacity, boolean direct)

 

// Allocates a new buffer with a specific size

public static IoBuffer allocate(int capacity)

allocate()方法接受一個或兩個引數。第一種形式有兩個引數:

  1. capacity - 緩衝區的容量
  2. 直接型緩衝區。如果獲取直接緩衝區為true,則為false以獲取堆緩衝區

預設緩衝區分配由SimpleBufferAllocator處理

或者,也可以使用以下形式

// Allocates heap buffer by default.
IoBuffer.setUseDirectBuffer(false);
// A new heap buffer is returned.
IoBuffer buf = IoBuffer.allocate(1024);

使用第二種形式時,不要忘記先設定預設緩衝區型別,否則預設情況下會獲得堆緩衝區。

建立自動擴充套件緩衝區

使用java NIO API建立自動擴充套件緩衝區並不是很容易,因為緩衝區的大小是固定的。擁有可以自動擴充套件需求的緩衝區對於網路應用程式來說是一個很大的優勢。為了解決這個問題,IoBuffer引入了autoExpand屬性。它會自動擴充套件其容量並限制值。

讓我們看看如何建立自動擴充套件緩衝區:

IoBuffer buffer = IoBuffer.allocate(8);
buffer.setAutoExpand(true);
buffer.putString("12345678", encoder);
// Add more to this buffer
buffer.put((byte)10);
 

如果在上面的示例中編碼資料大於8個位元組,則底層ByteBuffer由場景後面的IoBuffer重新分配。它的容量將加倍,其限制將增加到字串寫入的最後位置。此行為與StringBuffer類的工作方式非常相似。

注意:

這種機制很可能會從MINA 3.0中刪除,因為它並不是處理增加的緩衝區大小的最佳方法。它應該被隱藏列表的InputStream或固定大小的ByteBuffers陣列所取代。

建立自動縮小緩衝區

有些情況需要從緩衝區釋放額外分配的位元組,以保留記憶體。 IoBuffer提供autoShrink屬性來滿足需要。如果啟用了autoShrink,則在呼叫compact()時,IoBuffer會將緩衝區的容量減半,並且僅使用當前容量的1/4或更少。要手動收縮緩衝區,請使用shrink()方法。

讓我們看看這個:

IoBuffer buffer = IoBuffer.allocate(16);
buffer.setAutoShrink(true);
buffer.put((byte)1);
System.out.println("Initial Buffer capacity = "+buffer.capacity());
buffer.shrink();
System.out.println("Initial Buffer capacity after shrink = "+buffer.capacity());
buffer.capacity(32);
System.out.println("Buffer capacity after incrementing capacity to 32 = "+buffer.capacity());
buffer.shrink();
System.out.println("Buffer capacity after shrink= "+buffer.capacity());

我們最初將容量分配為16,並將autoShrink屬性設定為true。

讓我們看看這個的輸出:

Initial Buffer capacity = 16
Initial Buffer capacity after shrink = 16
Buffer capacity after incrementing capacity to 32 = 32
Buffer capacity after shrink= 16

讓我們休息一下並分析輸出:

1.初始緩衝區容量為16,因為我們建立了具有此容量的緩衝區。在內部,這成為緩衝區的最小容量

2.在呼叫shrink()之後,容量保持為16,因為容量永遠不會小於最小容量

3.將容量增加到32後,容量變為32

4.呼叫shrink(),將容量減少到16,從而消除額外的儲存空間

同樣,這個機制應該是預設機制,而不需要明確地告訴緩衝區它可以縮小。

緩衝區分配

IoBufferAllocater負責分配和管理緩衝區。要精確控制緩衝區分配策略,請實現IoBufferAllocater介面。

MINA附帶以下IoBufferAllocater實現:

1.SimpleBufferAllocator(預設) - 每次建立一個新緩衝區 2.CachedBufferAllocator - 快取可能在擴充套件期間重用的緩衝區

使用新的可用JVM,使用快取的IoBuffer不太可能提高效能。

您可以實現自己的IoBufferAllocator實現,並在IoBuffer上呼叫setAllocator()來使用它。