Java NIO中的通道Channel(二)分散/聚集 Scatter/Gather。本站提示廣大學習愛好者:(Java NIO中的通道Channel(二)分散/聚集 Scatter/Gather)文章只能為提供參考,不一定能成為您想要的結果。以下是Java NIO中的通道Channel(二)分散/聚集 Scatter/Gather正文
scatter/gather指的在多個緩沖區上實現一個簡單的I/O操作,比如從通道中讀取數據到多個緩沖區,或從多個緩沖區中寫入數據到通道;
scatter(分散):指的是從通道中讀取數據分散到多個緩沖區Buffer的過程,該過程會將每個緩存區填滿,直至通道中無數據或緩沖區沒有空間;
gather(聚集):指的是將多個緩沖區Buffer聚集起來寫入到通道的過程,該過程類似於將多個緩沖區的內容連接起來寫入通道;
scatter/gather接口如下是ScatteringByteChannel接口和GatheringByteChannel接口的定義,我們可以發現,接口中定義的方法都傳入了一個Buffer數組;
所謂的scatter/gather操作就是聚集(gather)這個Buffer數組並寫入到一個通道,或讀取通道數據並分散(scatter)到這個Buffer數組中;
public interface ScatteringByteChannel extends ReadableByteChannel { public long read(ByteBuffer[] dsts) throws IOException; public long read(ByteBuffer[] dsts, int offset, int length) throws IOException; } public interface GatheringByteChannel extends WritableByteChannel { public long write(ByteBuffer[] srcs) throws IOException; public long write(ByteBuffer[] srcs, int offset, int length) throws IOException; }
提醒下,帶offset和length參數的read( ) 和write( )方法可以讓我們只使用緩沖區數組的子集,注意這裡的offset指的是緩沖區數組索引,而不是Buffer數據的索引,length指的是要使用的緩沖區數量;
如下代碼,將會往通道寫入第二個、第三個、第四個緩沖區內容;
int bytesRead = channel.write (fiveBuffers, 1, 3);
注意,無論是scatter還是gather操作,都是按照buffer在數組中的順序來依次讀取或寫入的;
gather寫入scatter / gather經常用於需要將傳輸的數據分開處理的場合,下面我們看一下一個聚集寫入的示例:
ByteBuffer header = ByteBuffer.allocate(128); ByteBuffer body = ByteBuffer.allocate(1024); //write data into buffers ByteBuffer[] bufferArray = { header, body }; channel.write(bufferArray);
以上代碼會將header和body這兩個緩沖區的數據寫入到通道;
這裡要特別注意的並不是所有數據都寫入到通道,寫入的數據要根據position和limit的值來判斷,只有position和limit之間的數據才會被寫入;
舉個例子,假如以上header緩沖區中有128個字節數據,但此時position=0,limit=58;那麼只有下標索引為0-57的數據才會被寫入到通道中;
如下是一個分散讀取的示例:
ByteBuffer header = ByteBuffer.allocate(128); ByteBuffer body = ByteBuffer.allocate(1024); ByteBuffer[] bufferArray = { header, body }; channel.read(bufferArray);
以上代碼會將通道中的數據依次寫入到Buffer中,當一個buffer被寫滿後,channel緊接著向另一個buffer中寫;
舉個例子,假如通道中有200個字節數據,那麼header會被寫入128個字節數據,body會被寫入72個字節數據;
好處更加高效(以下內容摘自《JAVA NIO》);
大多數現代操作系統都支持本地矢量I/O(native vectored I/O)操作。
當您在一個通道上請求一個Scatter/Gather操作時,該請求會被翻譯為適當的本地調用來直接填充或抽取緩沖區,減少或避免了緩沖區拷貝和系統調用;
Scatter/Gather應該使用直接的ByteBuffers以從本地I/O獲取最大性能優勢;
參考資料《Java NIO》
http://ifeve.com/java-nio-scattergather/