上一篇知道了Buffer的工作机制,以及FileChannel的简单用法,这一篇介绍下 Scatter&Gather

1.Scatter(分散)

用于描述在Channel中读取的数据分散在不同的Buffer里。

接着上一篇的例子(rua文件内容为123456789),改造下代码:


readFile = new RandomAccessFile("D:\\rua.txt", "r");
FileChannel readChannel = readFile.getChannel();
ByteBuffer first = ByteBuffer.allocate(2); //第一块buffer
ByteBuffer second = ByteBuffer.allocate(2); //第二块buffer
ByteBuffer[] byteBuffers = {first, second};
long bytesRead = readChannel.read(byteBuffers); //从通道里读取数据到Buffer内(最大不超过Buffer容积)
while (bytesRead != -1) { //当读不到任何东西时返回-1
System.out.println("\nheader里的数据------此时byteRead=" + bytesRead);
first.flip(); //切换到Buffer读模式,读模式下可以读取到之前写入Buffer的数据
while (first.hasRemaining()) {
System.out.print("-" + (char) first.get()); //第一块Buffer读出的数据用减号分割,用于跟第二块区分
}
first.clear();
System.out.println("\nbody里的数据------此时byteRead=" + bytesRead);
second.flip();
while (second.hasRemaining()) {
System.out.print("+" + (char) second.get()); //第二块Buffer读出的数据用加号分割,用于跟第一块区分
}
second.clear(); // 切换回Buffer的写模式
System.out.println("\n----------------------------------------------");
bytesRead = readChannel.read(byteBuffers); //跟上面一样,再次从通道读取数据到Buffer中
}
System.out.print("\n-----------程序结束");

上面的代码开了两个Buffer,然后传给了Channel.read一个Buffer数组,运行结果如下:


header里的数据------此时byteRead=4
-1-2
body里的数据------此时byteRead=4
+3+4
---------------------------------------------- header里的数据------此时byteRead=4
-5-6
body里的数据------此时byteRead=4
+7+8
---------------------------------------------- header里的数据------此时byteRead=1
-9
body里的数据------此时byteRead=1 ---------------------------------------------- -----------程序结束

可以看到,文件里的内容被分段加载出来了,first buffer里首选读取一段,然后接着second buffer再接着读取接下来的一段。上面例子符合Scatter的描述。

看过网上一些文章,说的最多的例子就是协议头数据体分开处理的例子:

假设通过Channel获取到的数据存在固定长度的协议头,以及已知最大长度限制的数据体,就可以通过两个Buffer来接收,一个是header buffer,一个是body buffer,

但这个对数据要求很严苛,结合上面的例子,不难发现,想要做到准确无误的处理这个例子,就得要求事先必须知道header的长度,以及数据体的最大长度上限,为什么要这样呢?因为如果不知道header的长度,那么header buffer就可能会读到body buffer里的东西或者body buffer里读到header buffer里的东西,如果不知道body的上限长度,那么如果body数据长度超过了body buffer的长度,body里的数据就会再次读到header buffer中去(这个可以结合上面的例子理解)。

2.Gather(聚集)

用于描述在将不同Buffer里的数据写到同一个Channel中去。

来看个例子:


readFile = new RandomAccessFile("D:\\haha.txt", "rw");
FileChannel channel = readFile.getChannel();
ByteBuffer first = ByteBuffer.allocate(5); //第一块buffer
ByteBuffer second = ByteBuffer.allocate(5); //第二块buffer
first.put("aa".getBytes());
second.put("bb".getBytes());
first.flip();
second.flip();
ByteBuffer[] byteBuffers = {first, second};
channel.write(byteBuffers);
System.out.print("\n-----------程序结束");

运行结束后,haha.txt里的内容为:


aabb

可以看到,最终写入的数据就是按照顺序把两个buffer里的内容传输进去了。

同样的,还是以网上的协议头数据体的例子说事儿,这个跟Scatter下的传输方式比较起来就不会那么严格了,看到上面,初始容积为5个字节,但实际写到文件里的每个buffer仍然是两个字节,因为Gather模式下,Channel读取Buffer数据的时候,只会读取position到limit间的数据(可读区域),因此这里不用像多Buffer读一样要求那么严格,我们可以随意定义header buffer的长度,只要大于协议头本身长度即可,body buffer的要求其实是同上,也是大于数据体的长度上限即可。

这就是Scatter和Gather的全部内容了~其实简单理解,就是多Buffer操作,以及对网上那个例子,进行了更详细一点的说明。

Java NIO学习与记录(三): Scatter&Gather介绍及使用的更多相关文章

  1. Java NIO学习与记录(八): Reactor两种多线程模型的实现

    Reactor两种多线程模型的实现 注:本篇文章例子基于上一篇进行:Java NIO学习与记录(七): Reactor单线程模型的实现 紧接着上篇Reactor单线程模型的例子来,假设Handler的 ...

  2. Java NIO 学习笔记(三)----Selector

    目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...

  3. Java NIO学习与记录(五): 操作系统的I/O模型

    操作系统的I/O模型 在开始介绍NIO Reactor模式之前,先来介绍下操作系统的五种I/O模型,了解了这些模型,对理解java nio会有不小的帮助. 先来看下一个服务端处理一次网络请求的流程图: ...

  4. Java NIO学习与记录(二):FileChannel与Buffer用法与说明

    FileChannel与Buffer用法与说明 上一篇简单介绍了NIO,这一篇将介绍FileChannel结合Buffer的用法,主要介绍Buffer FileChannel的简单使用&Buf ...

  5. Java NIO学习与记录(七): Reactor单线程模型的实现

    Reactor单线程模型的实现 一.Selector&Channel 写这个模型需要提前了解Selector以及Channel,之前记录过FileChannel,除此之外还有以下几种Chann ...

  6. Java NIO学习与记录(六): NIO线程模型

    NIO线程模型 上一篇说的是基于操作系统的IO处理模型,那么这一篇来介绍下服务器端基于IO模型和自身线程的处理方式. 一.传统阻塞IO模型下的线程处理模式 这种处理模型是基于阻塞IO进行的,上一篇讲过 ...

  7. Java NIO学习与记录(一):初识NIO

    初识 工作中有些地方用到了netty,netty是一个NIO框架,对于NIO却不是那么熟悉,这个系列的文章是我在学习NIO时的一个记录,也期待自己可以更好的掌握NIO. 一.NIO是什么? 非阻塞式I ...

  8. Java NIO学习与记录(四): SocketChannel与BIO服务器

    SocketChannel与BIO服务器 SocketChannel可以创建连接TCP服务的客户端,用于为服务发送数据,SocketChannel的写操作和连接操作在非阻塞模式下不会发生阻塞,这篇文章 ...

  9. Java NIO 学习笔记(二)----聚集和分散,通道到通道

    目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...

随机推荐

  1. 全球数据库-->基金/管理产品-->分类/行业平均-->开放式分类

    SecID 招募书中所定净费率 换手率% 回报日期(每日) 计价货币 回报-本月以来(每日)计价货币 回报-本季以来(每日)计价货币 回报-本年以来(每日)计价货币 回报-1日(每日)计价货币 回报- ...

  2. http://4526621.blog.51cto.com/4516621/1343369

    http://4526621.blog.51cto.com/4516621/1343369

  3. SVN下的文件被locked不能update和commit

    一次早上开机svn更新代码,提示某一个文件夹被locked,提示clean up,但是clearn up也不行,get lock不行,release lock不行 根据网上搜的,.svn(隐藏文件夹) ...

  4. RocketMQ 使用及常见问题

    前言 本文档是针对RocketMQ使用及常见问题的说明. 一.获取项目.安装包及文档 1. alibaba/RocketMQ https://github.com/alibaba/RocketMQ 2 ...

  5. 布局分析002:入门级的CSS导航弹出菜单

    这种弹出菜单非常有意思,也有记录的意义,甚至可以说,掌握了这种弹出菜单,基本上CSS掌握的差不多. 主要涉及下面三个重要知识: CSS的继承性质. relative absolute定位. 子选择符& ...

  6. line-height:150% 和 line-height:1.5

    line-height属性的细节与大多数CSS属性不同,line-height支持属性值设置为无单位的数字.有无单位在子元素继承属性时有微妙的不同. 有单位(包括百分比)与无单位之间的区别有单位时,子 ...

  7. Deep learning for visual understanding: A review

    https://www.sciencedirect.com/science/article/pii/S0924271618301291?dgcid=raven_sd_recommender_email ...

  8. linux网络管理员

    1. 查看当前开启的所有网络服务 命令:netstat -a (all)显示所有选项,默认不显示LISTEN相关-t (tcp)仅显示tcp相关选项-u (udp)仅显示udp相关选项-n 拒绝显示别 ...

  9. Javascript设计模式理论与实战:适配器模式

    有的时候在开发过程中,我们会发现,客户端需要的接口和提供的接口发生不兼容的问题.由于特殊的原因我们无法修改客户端接口.在这种情况下,我们需要适配现有接口和不兼容的类,这就要提到适配器模式.通过适配器, ...

  10. 【原创】在Windows系统中使用VC9、VC11编译32位、64位PHP及其扩展

    项目中需要使用runkit模块实现AOP,但是团队成员的开发环境都是Windows,而runkit模块官方没有提供Windows环境下的dll扩展,只能自己编译. 下面是编译过程的分类总结.(操作系统 ...