庖丁解牛:NIO核心概念与机制详解 04 _ 分散和聚集
文章目录
- Pre
- 概述
- 分散/聚集 I/O
- 分散/聚集的应用
- 聚集写入
- Code

Pre
庖丁解牛:NIO核心概念与机制详解 01
庖丁解牛:NIO核心概念与机制详解 02 _ 缓冲区的细节实现
庖丁解牛:NIO核心概念与机制详解 03 _ 缓冲区分配、包装和分片
概述
分散/聚集 I/O 是使用多个而不是单个缓冲区来保存数据的读写方法。
- 一个分散的读取就像一个常规通道读取,只不过它是将数据读到一个缓冲区数组中而不是读到单个缓冲区中。
- 同样地,一个聚集写入是向缓冲区数组而不是向单个缓冲区写入数据。
分散/聚集 I/O 对于将数据流划分为单独的部分很有用,这有助于实现复杂的数据格式。

分散/聚集 I/O
通道可以有选择地实现两个新的接口: ScatteringByteChannel 和 GatheringByteChannel
一个 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 );}}
}

相关文章:
庖丁解牛:NIO核心概念与机制详解 04 _ 分散和聚集
文章目录 Pre概述分散/聚集 I/O分散/聚集的应用聚集写入Code Pre 庖丁解牛:NIO核心概念与机制详解 01 庖丁解牛:NIO核心概念与机制详解 02 _ 缓冲区的细节实现 庖丁解牛:NIO核心概念与机制详解 03 _ 缓冲区分配、包装和分片 概述 分散/聚…...
Java读写Jar
Java提供了读写jar的类库Java.util.jar,Java获取解析jar包的工具类如下: import java.io.File; import java.io.IOException; import java.net.URL; import java.net.URLClassLoader; import java.util.Enumeration; import java.util.HashMap; import …...
【四元数简述】
w cos(theta/2) x ax * sin(theta/2) y ay * sin(theta/2) z az * sin(theta/2) 向量(x,y,z)是旋转轴 a 是任意正数 theta是旋转角度。 上面就是一个四元数表示旋转。 如何使用 空间中向量(1,2,3)扩展为(0,1,2,3&#…...
ClickHouse SQL 查询优化
1 单表查询 1.1 Prewhere替代where Prewhere和where语句的作用相同,用来过滤数据。不同之处在于prewhere只支持 *MergeTree 族系列引擎的表,首先会读取指定的列数据,来判断数据过滤,等待数据过滤之后再读取select 声明的列字段来补…...
「Verilog学习笔记」数据选择器实现逻辑电路
专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点,刷题网站用的是牛客网 分析 将变量A、B接入4选1数据选择器选择输入端S0 S1。将变量C分配在数据输入端。从表中可以看出输出L与变量C的关系。 当AB00时选通D0而此时L0,所以数据端D0接0…...
【Go入门】Web工作方式
【Go入门】 Web工作方式 我们平时浏览网页的时候,会打开浏览器,输入网址后按下回车键,然后就会显示出你想要浏览的内容。在这个看似简单的用户行为背后,到底隐藏了些什么呢? 对于普通的上网过程,系统其实是这样做的&…...
综述:目标检测二十年(机翻版)(未完
原文地址 20年来的目标检测:一项调查 摘要关键词一 介绍二 目标检测二十年A.一个目标检测的路线图1)里程碑:传统探测器Viola Jones探测器HOG检测器基于可变形零件的模型(DPM) 2)里程碑:基于CNN的两阶段探测器RCNNSPPN…...
quinn源码解析:QUIC数据包是如何发送的
quinn源码解析:QUIC数据包是如何发送的 简介QUIC协议中的概念endpoint(端点)connection(连接)Stream(流)Frame (帧) 发包过程解析SendStream::write_allConnectionDriverEndpointDriver 简介 q…...
scss的高级用法——循环
周末愉快呀!一起来学一点简单但非常有用的css小知识。 最近在一个项目中看到以下css class写法: 了解过tailwind css或者unocss的都知道,从命名就可以看出有以下样式: font-size: 30pxmargin-left: 5px;margin-top: 10px; 于是…...
Linux安装Chrome浏览器 -linux安装choeme
Linux 操作系统一般自带的浏览器是 FireFox,不过有些用户可能更喜欢 Google 出品的 Chrome 浏览器。本教程将介绍如何在 Linux 系统上安装 Chrome 浏览器,以及可能会遇到的一些问题解决方案。 下载 Chrome 安装包 需要下载 Chrome 的安装包。可以在 Go…...
六大排序(插入排序、希尔排序、冒泡排序、选择排序、堆排序、快速排序)未完
文章目录 排序一、 排序的概念1.排序:2.稳定性:3.内部排序:4.外部排序: 二、插入排序1.直接插入排序2.希尔排序 三、选择排序1.直接选择排序方法一方法二直接插入排序和直接排序的区别 2.堆排序 四、交换排序1.冒泡排序2.快速排序…...
JVM垃圾回收相关概念
目录 一、System.gc()的理解 二、内存溢出与内存泄露 (一)OOM (二)内存泄露 三、StopTheWorld 四、垃圾回收的并行与并发 五、安全点与安全区域 (一)安全点 (二)安全区域 …...
C++各种字符转换
C各种字符转换 一.如何将char数组转化为string类型二. string转char数组:参考 一.如何将char数组转化为string类型 在C中,可以使用string的构造函数或者赋值操作符来将char数组转换为string类型。 方法1:使用string的构造函数 const char* c…...
MSSQL-逻辑级常用命令
--SQL Server 查询表的记录数 --one: 使用系统表. SELECT object_name (i.id) TableName, rows as RowCnt FROM sysindexes i INNER JOIN sysObjects o ON (o.id i.id AND o.xType U ) WHERE indid < 2 ORDER BY rows desc ————————————…...
【如何学习Python自动化测试】—— 时间等待
3 、 时间等待 在做自动化测试时,难免会碰到一些问题,比如你在脚本中操作某个对象时, 页面还没有加载出来,你的操作语句已经被执行,从而导致脚本执行失败,针对这样的问题 webdriver 提供了等待操作…...
《数字图像处理-OpenCV/Python》连载(44)图像的投影变换
《数字图像处理-OpenCV/Python》连载(44)图像的投影变换 本书京东优惠购书链接:https://item.jd.com/14098452.html 本书CSDN独家连载专栏:https://blog.csdn.net/youcans/category_12418787.html 第 6 章 图像的几何变换 几何变…...
AI机器学习 | 基于librosa库和使用scikit-learn库中的分类器进行语音识别
专栏集锦,大佬们可以收藏以备不时之需 Spring Cloud实战专栏:https://blog.csdn.net/superdangbo/category_9270827.html Python 实战专栏:https://blog.csdn.net/superdangbo/category_9271194.html Logback 详解专栏:https:/…...
Asp.net MVC Api项目搭建
整个解决方案按照分层思想来划分不同功能模块,以提供User服务的Api为需求,各个层次的具体实现如下所示: 1、新建数据库User表 数据库使用SQLExpress版本,表的定义如下所示: CREATE TABLE [dbo].[User] ([Id] …...
C语言中文网 - Shell脚本 - 8
第1章 Shell基础(开胃菜) 8. Linux Shell命令提示符 启动 Linux 桌面环境自带的终端模拟包,或者从 Linux 控制台登录后,便可以看到 Shell 命令提示符。看见命令提示符就意味着可以输入命令了。命令提示符不是命令的一部分&#x…...
性能测试学习——项目环境搭建和Jmete学习二
项目环境搭建、Jmeter学习二 环境的部署虚拟机的安装虚拟机中添加项目操作步骤 使用环境的注意事项Jmeter的安装和简单使用Jemter的使用的进阶Jemter元件 Jmeter属性执行顺序和作用域作用域以自定义用户变量和用户参数(前置处理器)为例如何解决用户变量和线程组同级时ÿ…...
Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...
黑马Mybatis
Mybatis 表现层:页面展示 业务层:逻辑处理 持久层:持久数据化保存 在这里插入图片描述 Mybatis快速入门 
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
Python 实现 Web 静态服务器(HTTP 协议)
目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1)下载安装包2)配置环境变量3)安装镜像4)node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1)使用 http-server2)详解 …...
Golang——7、包与接口详解
包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...
