Scatter(分散读)指一次从通道读取数据并按序填充多个ByteBuffer,适用于消息拆解为头/负载/校验等段;Gather(聚集写)指一次向通道写入多个ByteBuffer的剩余内容,适用于协议头、正文、尾部拼装后批量发送。

Java 中的 Scatter 和 Gather 读写主要通过 java.nio.channels.ScatteringByteChannel 和 GatheringByteChannel 接口实现,底层依赖于 ByteBuffer 数组的批量操作,常用于高性能网络通信(如 NIO Socket)或文件 I/O 场景。核心不是“手动模拟”,而是使用标准 API 直接调用 read(ByteBuffer[]) 和 write(ByteBuffer[]) 方法。
什么是 Scatter(分散读)
Scatter 指一次从通道中读取数据,自动按顺序填充多个 ByteBuffer(从第一个开始填满再填下一个),适用于将一条消息拆解为头部、负载、校验等逻辑段。
使用前提:通道必须实现 ScatteringByteChannel(如 SocketChannel、FileChannel)。
- 声明多个
ByteBuffer,例如:ByteBuffer header = ByteBuffer.allocate(4); ByteBuffer body = ByteBuffer.allocate(1024); - 调用
channel.read(new ByteBuffer[]{header, body}) - 注意:每个 buffer 必须已调用
flip()前置(实际 read 会自动处理 position/limit,但需确保 capacity 足够且未只读) - 返回值是本次总共读取的字节数;若为 -1 表示 EOF
什么是 Gather(聚集写)
Gather 指一次向通道写入数据,自动按顺序从多个 ByteBuffer 中提取内容(从第一个 remaining 部分开始,写完再写下一个),适合将协议头、正文、尾部等拼装后一次性发出,避免多次系统调用。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
使用前提:通道必须实现 GatheringByteChannel(同样如 SocketChannel、FileChannel)。
- 准备多个已
flip()的 buffer(确保 limit ≤ capacity,position = 0) - 调用
channel.write(new ByteBuffer[]{header, body, footer}) - 所有 buffer 会被按序读取,但不会修改其内容;写完后各 buffer 的 position 会前移对应字节数
- 返回值为本次实际写出的总字节数
关键注意事项
Scatter/Gather 不是线程安全的,多线程并发访问同一通道时需同步;且仅对直接缓冲区(DirectBuffer)或堆外内存有显著性能优势。
- buffer 数组中不能含 null,否则抛
NullPointerException - 如果某 buffer 是只读的,对应部分将跳过(不报错,但 write 返回值不含该段长度)
- 阻塞模式下,read/write 可能只完成部分 buffer;非阻塞模式需结合
SelectionKey.OP_READ/WRITE循环处理 - 文件通道支持 scatter/gather,但必须是可读写的(
FileChannel.open(..., READ, WRITE))
简单示例:SocketChannel 的请求头+体分离读取
假设协议前 4 字节是 int 类型长度,后续是 JSON 内容:
ByteBuffer lenBuf = ByteBuffer.allocate(4); ByteBuffer jsonBuf = ByteBuffer.allocate(8192);int n = channel.read(new ByteBuffer[]{lenBuf, jsonBuf});- 读完后检查:
if (n > 0 && lenBuf.position() == 4),再用lenBuf.getInt(0)解析真实体长 - 注意:若首次 read 只读到 2 字节,
lenBuf.position()就是 2,此时需继续 read 直到填满头部

















