五、Java NIO Scatter / Gather
所有文章
https://www.cnblogs.com/lay2017/p/12901123.html
正文
在前面的文章中,我们默认了一个规则。就是默认了一个Channel对应了一个Buffer,它们之间的读写发生在一对一关系里。事实上,Channel是可以对应多个Buffer的,也就是一对多关系。
当一个Channel向多个Buffer写入数据的时候,称作分散(Scatter)
当一个Channel从多个Buffer读取数据的数据,称作聚集(Gather)
分散读取(Scattering Read)
分散读取意味着从一个Channel中读取数据到多个Buffer里面。如图:
以下是示例代码
ByteBuffer header = ByteBuffer.allocate(128); ByteBuffer body = ByteBuffer.allocate(1024); ByteBuffer[] bufferArray = { header, body }; channel.read(bufferArray);
注意,示例中首先创建了两个Buffer:header、body,分别具备固定大小。header、body再放到一个array当中。Channel向Buffer读数据的时候入参是array。
我们关注一个read方法的逻辑,read方法传入了两个Buffer。当第一个Buffer满了以后,才会开始往第二个Buffer填充数据。也就是说其内部是遍历Buffer来填充数据的,当前一个Buffer没有满的情况下是不会移动到下一个Buffer的。这意味着,分散读取到多个Buffer并不适用于大小是动态的。换句话说,如果header的大小不是固定的,那么使用过程中可能就会出现body的数据在header的Buffer中,这就造成了一些问题。所以分散读取到多个Buffer,需要Buffer大小相对固定。
聚集写入(gathering write)
聚集写入,是将多个Buffer的数据写入到一个Channel当中,如图
以下是示例代码
ByteBuffer header = ByteBuffer.allocate(128); ByteBuffer body = ByteBuffer.allocate(1024); //write data into buffers ByteBuffer[] bufferArray = { header, body }; channel.write(bufferArray);
类似地,传入了多个Buffer。当write方法执行地时候,会按照顺序从Buffer中读入数据,并写入到Channel当中。不过和分散读不同地是,聚集写不需要Buffer固定大小。一个Buffer只要读完数据就会换下一个Buffer。