Java NIO Scatter/Gather

94 阅读2分钟

Java NIO 带来内置的scatter和gather支持。Scatter/gather的观念被用在从channel里读取和写数据到channel。

从channel里的scattering是一个读取操作,可以读取更多buffer里的数据。也意味着channel "scatter"将数据从channel到多个buffers。

gathering写到channel是一个写操作,可以从多个buffer里写到单个channel里。意味着 channel从多个buffer里"gathers"数据到一个channel里。

Scatter/gather 在某些需要使用分别传输的数据的场景里是非常有用的。例如,如果一个消息由头部和主体组成,你也许将头部和主体保持他们处在在不同的buffer里。如果使用这个技术可以让你更加简单的同分开的头部和主体工作。

Scattering Reads

一个"scattering read"从单个channel读取数据到多个buffers里。这里是这个原理的说明:

这里是Scatter原理的图表

Java NIO: Scattering Read

下面是一个示例代码展示了怎么执行scatting 读:

ByteBuffer header = ByteBuffer.allocate(128);
ByteBuffer body   = ByteBuffer.allocate(1024);

ByteBuffer[] bufferArray = { header, body };

channel.read(bufferArray);

注意buffer是怎么先插入到一个数组里的,然后数组传递一个参数给channel.read()方法。read()方法从出现在数组里的buffer顺序里向channel写数据。一旦一个buffer写满,channel移动到下一个buffer去填充。

实际上scattering 在读取下一个之前已经填充完一个buffer,意味着跟动态大小的数据场景不匹配。换句话说,如果你有一个头部和主体,并且head是固定的大小(比如128bytes),scattering 读取会非常好。

Gathering Writes

一个"gathering write"是从多个buffer里写数据到单个channel。这里是原理的说明:

Java NIO: Gathering Wwrite

这里是简单的代码示例,展示了怎么执行gathering 写:

ByteBuffer header = ByteBuffer.allocate(128);
ByteBuffer body   = ByteBuffer.allocate(1024);

ByteBuffer[] bufferArray = { header, body };

channel.write(bufferArray);

buffer数组传递到write()方法,这个方法写数组里顺序出现的buffer的内容。仅当数据在position和buffer的limit才写入。意味着,如果一个buffer的容量是128字节,但是只包含58字节的内容,只有58字节从buffer里写到channel。因此,一个gathering 写操作在动态消息大小的场景里工作非常好,这里同scatter读相反。