Java NIO系列教程(四) Scatter/Gather

原文地址:http://tutorials.jenkov.com/java-nio/scatter-gather.html

作者:Jakob Jenkov   译者:郭蕾   

Java NIO开始支持scatter/gather,scatter/gather用于描述从Channel(译者注:Channel在中文经常翻译为通道)中读取或者写入到Channel的操作。
分散(scatter)从Channel中读取是指在读操作时将读取的数据写入多个buffer中。因此,Channel将从Channel中读取的数据“分散(scatter)”到多个Buffer中。
聚集(gather)写入Channel是指在写操作时将多个buffer的数据写入同一个Channel,因此,Channel 将多个Buffer中的数据“聚集(gather)”后发送到Channel。

scatter / gather经常用于需要将传输的数据分开处理的场合,例如传输一个由消息头和消息体组成的消息,你可能会将消息体和消息头分散到不同的buffer中,这样你可以方便的处理消息头和消息体。

Scattering Reads
Scattering Reads是指数据从一个channel读取到多个buffer中。如下图描述:



Java NIO: Scattering Read

代码示例如下:

1 ByteBuffer header = ByteBuffer.allocate(128);
2 ByteBuffer body   = ByteBuffer.allocate(1024);
3  
4 ByteBuffer[] bufferArray = { header, body };
5  
6 channel.read(bufferArray);

注意buffer首先被插入到数组,然后再将数组作为channel.read() 的输入参数。read()方法按照buffer在数组中的顺序将从channel中读取的数据写入到buffer,当一个buffer被写满后,channel紧接着向另一个buffer中写。

Scattering Reads在移动下一个buffer前,必须填满当前的buffer,这也意味着它不适用于动态消息(译者注:消息大小不固定)。换句话说,如果存在消息头和消息体,消息头必须完成填充(例如 128byte),Scattering Reads才能正常工作。

Gathering Writes

Gathering Writes是指数据从多个buffer写入到同一个channel。如下图描述:



Java NIO: Gathering Write

代码示例如下:

1 ByteBuffer header = ByteBuffer.allocate(128);
2 ByteBuffer body   = ByteBuffer.allocate(1024);
3  
4 //write data into buffers
5  
6 ByteBuffer[] bufferArray = { header, body };
7  
8 channel.write(bufferArray);

buffers数组是write()方法的入参,write()方法会按照buffer在数组中的顺序,将数据写入到channel,注意只有position和limit之间的数据才会被写入。因此,如果一个buffer的容量为128byte,但是仅仅包含58byte的数据,那么这58byte的数据将被写入到channel中。因此与Scattering Reads相反,Gathering Writes能较好的处理动态消息。 

时间: 2024-08-01 01:02:51

Java NIO系列教程(四) Scatter/Gather的相关文章

Java NIO 系列教程

Java NIO(New IO)是从Java 1.4版本开始引入的一个新的IO API,可以替代标准的Java IO API.本系列教程将有助于你学习和理解Java NIO.感谢并发编程网的翻译和投递.  (关注ITeye官微,随时随地查看最新开发资讯.技术文章.)  [本文转载于 Java NIO 系列教程] Java NIO提供了与标准IO不同的IO工作方式:  Channels and Buffers(通道和缓冲区):标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channe

java的nio之:java的nio系列教程之Scatter/Gather

一:Java NIO的scatter/gather应用概念 ===>Java NIO开始支持scatter/gather,scatter/gather用于描述从Channel(译者注:Channel在中文经常翻译为通道)中读取或者写入到Channel的操作.===>分散(scatter)从Channel中读取是指在读操作时将读取的数据写入多个buffer中.因此,Channel将从Channel中读取的数据"分散(scatter)"到多个Buffer中.===>聚集(

Java NIO 系列教程(转)

原文中说了最重要的3个概念,Channel 通道Buffer 缓冲区Selector 选择器其中Channel对应以前的流,Buffer不是什么新东西,Selector是因为nio可以使用异步的非堵塞模式才加入的东西.以前的流总是堵塞的,一个线程只要对它进行操作,其它操作就会被堵塞,也就相当于水管没有阀门,你伸手接水的时候,不管水到了没有,你就都只能耗在接水(流)上.nio的Channel的加入,相当于增加了水龙头(有阀门),虽然一个时刻也只能接一个水管的水,但依赖轮换策略,在水量不大的时候,各

Java NIO系列教程(一) Java NIO 概述

原文链接     作者:Jakob Jenkov     译者:airu     校对:丁一 Java NIO 由以下几个核心部分组成: Channels Buffers Selectors 虽然Java NIO 中除此之外还有很多类和组件,但在我看来,Channel,Buffer 和 Selector 构成了核心的API.其它组件,如Pipe和FileLock,只不过是与三个核心组件共同使用的工具类.因此,在概述中我将集中在这三个组件上.其它组件会在单独的章节中讲到. Channel 和 Bu

Java NIO系列教程(三) Buffer

Java NIO中的Buffer用于和NIO通道进行交互.如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的. 缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存.这块内存被包装成NIO Buffer对象,并提供了一组方法,用来方便的访问该块内存. 下面是NIO Buffer相关的话题列表: Buffer的基本用法 Buffer的capacity,position和limit Buffer的类型 Buffer的分配 向Buffer中写数据 flip()方法 从Buffer中读取数据

Java NIO系列教程(三) Buffer(转)

Java NIO中的Buffer用于和NIO通道进行交互.如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的. 缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存.这块内存被包装成NIO Buffer对象,并提供了一组方法,用来方便的访问该块内存. 下面是NIO Buffer相关的话题列表: Buffer的基本用法 Buffer的capacity,position和limit Buffer的类型 Buffer的分配 向Buffer中写数据 flip()方法 从Buffer中读取数据

Java NIO系列教程(十二) Java NIO与IO

原文地址:http://tutorials.jenkov.com/java-nio/nio-vs-io.html 作者:Jakob Jenkov   译者:郭蕾    校对:方腾飞 当学习了Java NIO和IO的API后,一个问题马上涌入脑海: 我应该何时使用IO,何时使用NIO呢?在本文中,我会尽量清晰地解析Java NIO和IO的差异.它们的使用场景,以及它们如何影响您的代码设计. Java NIO和IO的主要区别 下表总结了Java NIO和IO之间的主要差别,我会更详细地描述表中每部分

Java NIO系列教程(十一) Pipe

原文链接     作者:Jakob Jenkov     译者:黄忠       校对:丁一 Java NIO 管道是2个线程之间的单向数据连接.Pipe有一个source通道和一个sink通道.数据会被写到sink通道,从source通道读取. 这里是Pipe原理的图示: 创建管道 通过Pipe.open()方法打开管道.例如: 1 Pipe pipe = Pipe.open(); 向管道写数据 要向管道写数据,需要访问sink通道.像这样: 1 Pipe.SinkChannel sinkCh

Java NIO系列教程(九) ServerSocketChannel

Java NIO中的 ServerSocketChannel 是一个可以监听新进来的TCP连接的通道, 就像标准IO中的ServerSocket一样.ServerSocketChannel类在 java.nio.channels包中. 这里有个例子: ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.socket().bind(new InetSocketAddres