读书笔记-《Java NIO》:第三章 通道(2)

来源:互联网 发布:windows ssid 编辑:程序博客网 时间:2024/06/05 12:01

封面女神系列,第二期-高圆圆O(∩_∩)O~

继续第三章的学习。。。


问题1: 什么是Scatter/Gather(发散/汇聚)?



操作系统中有一个概念Scatter/Gather,是什么意思呢?

有的操作系统设计的比较高效,允许进程只使用一个系统调用,就能够把一连串缓冲区地址传递给系统内核,之后内核就可以顺序填充或清除缓冲区。

Scatter就是指操作系统内核从磁盘读取到数据后,可以将读取的数据发散到多个用户缓冲区;Gather就是指多个缓冲区向磁盘写数据时,操作系统内核可以把多个缓冲区的数据聚合起来,然后再写入磁盘。这样用户进程就不需要多次执行系统调用了,多次系统调用的开销,一般都不小。

如下图所示,通过Scatter/Gather,用户进程调用一次内核的read()就可以同时操作3个用户空间的缓冲区。

Java NIO中有对应的ScatteringByteChannel和GatheringByteChannel通道,在Channel类图中的位置如下:

ScatteringByteChannel继承自ReadableByteChannel,并且新增了两个read方法;GatheringByteChannel继承自WritableByteChannel,新增了两个write方法。


问题2: Scatter/Gather怎么使用?



书中举了一个例子,分配两个直接缓冲区header和body,将header和body两个缓冲区组成数组,并将数组作为参数传递给Channel.read()。Channel通过调用系统内核,从磁盘读取数据后,会将前10个字节的数据存入header缓存,之后的数据存入body缓存。这就是Scatter

下面这个图会更形象些:

写的时候,是如下这种操作,将header、body缓冲去分别写入数据,再将header和body组合成数组,并作为参数传递给Channel.write()。这就是Gather。

Gather的时候,实际上就是将多个缓冲区的数据,合并到一个大的缓冲区中,再往磁盘上写。如下图所示。

Note:无论是Gather还是Scatter通道,都有一个包含offset和length参数的方法。这里offset可不是单个缓冲区内的偏移,而是缓冲区的偏移;length是使用缓冲区的个数,而不是长度,定义为count会更好些。

比如srcs包含5个缓冲区,Channel.write(srcs, 1, 3)表示的是从第二个缓冲区开始写,总共写3个缓冲区,也就是会写第2个,第3个和第4个缓冲区。

今天先到这儿,明天继续( ^_^ )


原创粉丝点击