zoukankan      html  css  js  c++  java
  • Java NIO中的通道Channel(二)分散/聚集 Scatter/Gather

    什么是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的数据才会被写入到通道中;

    scatter读取

    如下是一个分散读取的示例:

    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/

  • 相关阅读:
    HTML DOM教程 49JavaScript Number 对象
    jquery技巧总结
    eclipse常用快捷键汇总
    一个Hibernate 的简单教程
    HTML DOM教程 51JavaScript match() 方法
    Java开源项目Hibernate包作用详解
    Build system 英文说明 Andrlid.mk说明
    android通过 哪些变量 来决定 哪些应用 会被编译进系统
    android“设置”里的版本号
    android设置中PreferenceActivity的 小结
  • 原文地址:https://www.cnblogs.com/chenpi/p/6483431.html
Copyright © 2011-2022 走看看