当前位置: 首页 > news >正文

庖丁解牛:NIO核心概念与机制详解 04 _ 分散和聚集

文章目录

  • Pre
  • 概述
  • 分散/聚集 I/O
  • 分散/聚集的应用
  • 聚集写入
  • Code

在这里插入图片描述


Pre

庖丁解牛:NIO核心概念与机制详解 01

庖丁解牛:NIO核心概念与机制详解 02 _ 缓冲区的细节实现

庖丁解牛:NIO核心概念与机制详解 03 _ 缓冲区分配、包装和分片


概述

分散/聚集 I/O 是使用多个而不是单个缓冲区来保存数据的读写方法。

  • 一个分散的读取就像一个常规通道读取,只不过它是将数据读到一个缓冲区数组中而不是读到单个缓冲区中
  • 同样地,一个聚集写入是向缓冲区数组而不是向单个缓冲区写入数据

分散/聚集 I/O 对于将数据流划分为单独的部分很有用,这有助于实现复杂的数据格式。

在这里插入图片描述


分散/聚集 I/O

通道可以有选择地实现两个新的接口: ScatteringByteChannelGatheringByteChannel

一个 ScatteringByteChannel 是一个具有两个附加读方法的通道:

long read( ByteBuffer[] dsts );
long read( ByteBuffer[] dsts, int offset, int length );

这些 long read() 方法很像标准的 read 方法,只不过它们不是取单个缓冲区而是取一个缓冲区数组。

在 分散读取 中,通道依次填充每个缓冲区。填满一个缓冲区后,它就开始填充下一个。在某种意义上,缓冲区数组就像一个大缓冲区。


分散/聚集的应用

分散/聚集 I/O 对于将数据划分为几个部分很有用。

例如,

  • 可能在编写一个使用消息对象的网络应用程序,每一个消息被划分为固定长度的头部和固定长度的正文。
  • 可以创建一个刚好可以容纳头部的缓冲区和另一个刚好可以容难正文的缓冲区。当你将它们放入一个数组中并使用分散读取来向它们读入消息时,头部和正文将整齐地划分到这两个缓冲区中。

我们从缓冲区所得到的方便性对于缓冲区数组同样有效。因为每一个缓冲区都跟踪自己还可以接受多少数据,所以分散读取会自动找到有空间接受数据的第一个缓冲区。在这个缓冲区填满后,它就会移动到下一个缓冲区。


聚集写入

聚集写入 类似于分散读取,只不过是用来写入。它也有接受缓冲区数组的方法:

long write( ByteBuffer[] srcs );
long write( ByteBuffer[] srcs, int offset, int length );

聚集写对于把一组单独的缓冲区中组成单个数据流很有用。为了与上面的消息例子保持一致,我们可以使用聚集写入来自动将网络消息的各个部分组装为单个数据流,以便跨越网络传输消息。


Code

import java.io.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;public class UseScatterGather
{static private final int firstHeaderLength = 2;static private final int secondHeaderLength = 4;static private final int bodyLength = 6;static public void main( String args[] ) throws Exception {if (args.length!=1) {System.err.println( "Usage: java UseScatterGather port" );System.exit( 1 );}int port = Integer.parseInt( args[0] );ServerSocketChannel ssc = ServerSocketChannel.open();InetSocketAddress address = new InetSocketAddress( port );ssc.socket().bind( address );int messageLength =  firstHeaderLength + secondHeaderLength + bodyLength;ByteBuffer buffers[] = new ByteBuffer[3];buffers[0] = ByteBuffer.allocate( firstHeaderLength );buffers[1] = ByteBuffer.allocate( secondHeaderLength );buffers[2] = ByteBuffer.allocate( bodyLength );SocketChannel sc = ssc.accept();while (true) {// Scatter-read into buffersint bytesRead = 0;while (bytesRead < messageLength) {long r = sc.read( buffers );bytesRead += r;System.out.println( "r "+r );for (int i=0; i<buffers.length; ++i) {ByteBuffer bb = buffers[i];System.out.println( "b "+i+" "+bb.position()+" "+bb.limit() );}}// Process message here// Flip buffersfor (int i=0; i<buffers.length; ++i) {ByteBuffer bb = buffers[i];bb.flip();}// Scatter-write back outlong bytesWritten = 0;while (bytesWritten<messageLength) {long r = sc.write( buffers );bytesWritten += r;}// Clear buffersfor (int i=0; i<buffers.length; ++i) {ByteBuffer bb = buffers[i];bb.clear();}System.out.println( bytesRead+" "+bytesWritten+" "+messageLength );}}
}

在这里插入图片描述

http://www.lryc.cn/news/236313.html

相关文章:

  • Java读写Jar
  • 【四元数简述】
  • ClickHouse SQL 查询优化
  • 「Verilog学习笔记」数据选择器实现逻辑电路
  • 【Go入门】Web工作方式
  • 综述:目标检测二十年(机翻版)(未完
  • quinn源码解析:QUIC数据包是如何发送的
  • scss的高级用法——循环
  • Linux安装Chrome浏览器 -linux安装choeme
  • 六大排序(插入排序、希尔排序、冒泡排序、选择排序、堆排序、快速排序)未完
  • JVM垃圾回收相关概念
  • C++各种字符转换
  • MSSQL-逻辑级常用命令
  • 【如何学习Python自动化测试】—— 时间等待
  • 《数字图像处理-OpenCV/Python》连载(44)图像的投影变换
  • AI机器学习 | 基于librosa库和使用scikit-learn库中的分类器进行语音识别
  • Asp.net MVC Api项目搭建
  • C语言中文网 - Shell脚本 - 8
  • 性能测试学习——项目环境搭建和Jmete学习二
  • C++标准模板库(STL)-map介绍
  • 使用docker部署ELK日志框架-Elasticsearch
  • 第7章 模式匹配与正则表达式
  • 单元测试实战(三)JPA 的测试
  • 初刷leetcode题目(3)——数据结构与算法
  • 76基于matlab的免疫算法求解配送中心选址问题,根据配送地址确定最佳配送中心地址位置。
  • C++二分查找算法:找到 Alice 和 Bob 可以相遇的建筑
  • 建立跨层全栈的区块链安全保障系统-应用层,系统层,设施层
  • 程序员告诉你:人工智能是什么?
  • 飞书开发学习笔记(七)-添加机器人及发送webhook消息
  • C/C++统计数 2021年12月电子学会青少年软件编程(C/C++)等级考试一级真题答案解析