深入理解 Java NIO:ByteBuffer和MappedByteBuffer的特性与使用

目录

前言

ByteBuffer是什么

重要特点

分配缓冲区

读写模式切换

操作文本数据

操作基本数据类型

案例解析-循环输出数据

MappedByteBuffer是什么

MappedByteBuffer 的工作机制

刷盘时机

总结


前言

在深入学习 RocketMQ 这款高性能消息队列框架的源码时,发现 ByteBufferMappedByteBuffer在 RocketMQ 这样的高性能消息队列框架中扮演了关键角色,其核心部分广泛使用了这两种缓冲区,以实现高效的数据存储和异步刷盘操作。 接下来就深入学习ByteBuffer 和 MappedByteBuffer 的工作原理、优势特点,以便能运用到实际业务中。

ByteBuffer是什么

ByteBuffer 是 Java NIO(New Input/Output)库中的一个类,用于高效地进行字节数据的读写操作。ByteBuffer 提供了一个直接操作字节数组的接口,使得开发者可以更加灵活和高效地处理数据,特别是在处理大文件、网络通信以及其他需要高性能 I/O 操作的场景下。

重要特点

使用 ByteBuffer 进行数据读取时,内部的 position 指针会在每次读取操作后自动向前移动。这是 ByteBuffer 的基本操作原理之一,用于追踪缓冲区当前的读取或写入位置 。

分配缓冲区

ByteBuffer 类提供了两种主要的方法来分配缓冲区:allocateallocateDirect

ByteBuffer buffer = ByteBuffer.allocate(1024);
ByteBuffer directBuffer = ByteBuffer.allocateDirect(1024);
  • allocate:分配JVM堆内存中的缓冲区,所以它受 JVM 垃圾回收的管理, 在执行 I/O 操作时,可能需要将数据从堆内存复制到操作系统的 I/O 缓冲区中,相对于直接缓冲区,堆缓冲区的性能通常稍逊色,适合对性能要求不高的场景。
  • allocateDirect:分配的缓冲区是在 JVM 堆外的直接内存中,从而减少了内存复制的开销,适合需要高性能 I/O 操作的场景,由于直接缓冲区不受 JVM 垃圾回收的管理,它可能会造成内存泄漏,需要额外注意管理

读写模式切换

ByteBuffer 提供了 flip() 方法,可以方便地从写模式切换到读模式;clear() 方法可以重置缓冲区,使其再次可用于写入数据。

ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.flip();
buffer.clear();

操作文本数据

import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;public class ByteBufferExample {public static void main(String[] args) {String text = "Hello, ByteBuffer!";// 创建一个 ByteBufferByteBuffer byteBuffer = ByteBuffer.allocate(1024);// 将字符串转换为字节数组并逐个字节写入byteBuffer.put(text.getBytes(StandardCharsets.UTF_8));// 准备读取byteBuffer.flip();// 读取并输出 ByteBuffer 中的字节byte[] outputArray = new byte[byteBuffer.remaining()];byteBuffer.get(outputArray);String outputText = new String(outputArray, StandardCharsets.UTF_8);System.out.println("Stored and retrieved text: " + outputText);}
}
  • 其中ByteBuffer.remaining() 方法就是确定在当前缓冲区的 positionlimit 之间还有多少字节可以读取。它间接告诉你“从当前位置到缓冲区结束,可以读取的字节数”。

上面案例只是对单条数据进行操作,所以获取时直接调用remaining()方法获取所有可以读取的字节数并输出。

那么我们需要存储多条数据,并且逐条输出呢?

  • 对于固定大小的数据,可以直接逐条写入数据,并在读取时使用 get 方法按固定字节数读取。(对于实际业务中很难保证操作的文本数据大小一样)
  • 对于可变大小的数据,先存储每条数据的长度,然后存储数据内容;读取时先读取长度,再读取对应大小的数据内容。(显然这种维护成本很高)

操作基本数据类型

ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.putInt(1);
buffer.putLong(1L);
buffer.putFloat(1.0f);
buffer.putDouble(1.0);
...

我们知道一个基本数据类型的大小是固定的,所以ByteBuffer提供了相关方法

  • int 类型占用 4 个字节
  • long 类型占用 8 个字节
  • float 类型占用 4 个字节
  • double 类型占用 8 个字节

案例解析-循环输出数据

如果我们一条数据由20个字节组成,并且这20个字节是三个关键数据组合(基于RocketMq源码ConsumeQueue场景简化)

我们对2条数据进行存储并获取操作。

注意:获取顺序必须与写入顺序一致!!!

public static void main(String[] args) {ByteBuffer buffer = ByteBuffer.allocate(1024);//第一条数据buffer.putLong(637823L);buffer.putInt(233);buffer.putLong(232342L);//第二条数据buffer.putLong(34234L);buffer.putInt(33);buffer.putLong(34322L);//切换读模式buffer.flip();while (buffer.hasRemaining()){//偏移量long offset = buffer.getLong();//msg大小int msgSize = buffer.getInt();//标签大小long tagsSize = buffer.getLong();//拼接一条完整的数据String msgIndex = offset + "" + msgSize + "" + tagsSize;System.out.println("msgIndex:" + msgIndex);}
}

输出:

MappedByteBuffer是什么

MappedByteBufferByteBuffer 的一个子类,所以具有ByteBuffer 的所有特性,它核心是用于内存映射文件mmap机制的一种实现)。它通过将文件映射到内存,使得应用程序可以直接在内存中对文件内容进行读写操作,而操作系统负责在适当的时候将这些修改同步到磁盘上。这种机制极大地提高了文件 I/O 的效率。

MappedByteBuffer 的工作机制

  1. 内存映射文件的内容被映射到内存后,操作系统会在后台维护内存和磁盘之间的同步。应用程序对 MappedByteBuffer 的读写操作实际上是对内存的读写,操作系统会在适当的时候将这些修改写入到磁盘中。
  2. 异步刷盘操作系统通过页面缓存机制来管理内存和磁盘之间的数据同步。修改后的页面不会立即写回磁盘,而是被标记为“脏页”(dirty page)。当页面缓存需要释放内存或达到一定条件时,操作系统会将脏页刷盘。
  3. 手动刷盘MappedByteBuffer 提供了 force() 方法,允许应用程序立即将内存中的修改同步到磁盘。这个方法会触发操作系统将映射的内存区域中的脏页写回到文件中,确保数据的持久性。
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;public class MappedByteBufferExample {public static void main(String[] args) throws Exception {RandomAccessFile file = new RandomAccessFile("example.txt", "rw");FileChannel channel = file.getChannel();// 将文件的前 1024 字节映射到内存MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, 1024);// 在内存中修改数据buffer.put(0, (byte) 97);  // 写入 ASCII 码 'a'// 手动将内存中数据刷新到磁盘buffer.force();channel.close();file.close();}
}

刷盘时机

  • 在使用 MappedByteBuffer 进行内存映射文件操作时,除了显式调用 force() 方法触发刷盘外,其他刷盘操作由操作系统根据内存管理和 I/O 子系统的机制自行决定。应用程序通常无法确切知道刷盘的具体时间。
  • 可以通过日志、监控工具和文件系统统计信息了解系统的刷盘行为。为了确保关键数据的及时刷盘,可以显式调用刷盘方法并采用事务机制管理数据写入等。

总结

ByteBuffer 和 MappedByteBuffer 是 Java NIO 中重要的组件,通过提供高效的内存和文件操作机制,极大地提高了 I/O 操作的性能和灵活性。理解并掌握它们的使用,可以帮助我们在处理大数据量、高性能应用时游刃有余。通过学习它们的底层实现和应用场景,我们可以更好地优化应用程序的 I/O 操作,提高整体系统性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/50047.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

醒醒,别睡了...讲《数据分析pandas库》了—/—<1>

一、了解pandas No.1 Pandas 是 Python 语言的一个扩展程序库,用于数据分析,是一个强大的分析结构化数据的工具集,基础是Numpy库,可以去参考前面所讲的课。(提供高性能的矩阵运算) No.2 应用 :P…

vue上传Excel文件并直接点击文件列表进行预览

本文主要内容:用elementui的Upload 组件上传Excel文件,上传后的列表采用xlsx插件实现点击预览表格内容效果。 在项目中可能会有这样的需求,有很多种方法实现。但是不想要跳转外部地址,所以用了xlsx插件来解析表格,并展…

Docker安装kkFileView实现在线文件预览

kkFileView为文件文档在线预览解决方案,该项目使用流行的spring boot搭建,易上手和部署,基本支持主流办公文档的在线预览,如doc,docx,xls,xlsx,ppt,pptx,pdf,txt,zip,rar,图片,视频,音频等等 官方文档地址:https://kkview.cn/zh-cn/docs/production.html 一、拉取镜像 do…

1 深度学习网络DNN

代码来自B站up爆肝杰哥 测试版本 import torch import torchvisiondef print_hi(name):print(fHi, {name}) if __name__ __main__:print_hi(陀思妥耶夫斯基)print("HELLO pytorch {}".format(torch.__version__))print("torchvision.version:", torchvi…

用在ROS2系统中保持差速轮方向不变的PID程序

在ROS 2中,为了保持差速轮机器人的方向不变,通常需要使用PID(Proportional Integral Derivative)控制器来控制机器人的角速度。PID控制器可以帮助调整机器人的角速度,以维持其朝向不变。 下面是一个简单的ROS 2节点示…

使用el-table的案例小结——包含跨页多选、双击行、分页器、编辑\删除行、动态根据分页生成序号

首先看一下业务需求 需要实现跨页多选,双击行的时候弹出编辑对话框,对每行可以进行编辑和删除,实现分页器。 如果还没在项目中配置element-plus的可以参考文章 从零开始创建vue3项目——包含项目初始化、element-plus、eslint、axios、router…

vue import from

vue import from 导入文件,从XXXX路径;引入文件 import xxxx from “./minins/resize” import xxxx from “./minins/resize.js” vue.config.js 定义 : resolve(src);就是指src 目录 import xxxx from “/utils/auth” im…

【C++初阶】string类

【C初阶】string类 🥕个人主页:开敲🍉 🔥所属专栏:C🥭 🌼文章目录🌼 1. 为什么学习string类? 1.1 C语言中的字符串 1.2 实际中 2. 标准库中的string类 2.1 string类 2.…

Web响应式设计———1、Grid布局

1、网格布局 Grid布局 流动网格布局是响应式设计的基础。它通过使用百分比而不是固定像素来定义网格和元素的宽度。这样&#xff0c;页面上的元素可以根据屏幕宽度自动调整大小&#xff0c;适应不同设备和分辨率。 <!DOCTYPE html> <html lang"en"> &l…

Mysql-索引视图

目录 1.视图 1.1什么是视图 1.2为什么需要视图 1.3视图的作用和优点 1.4创建视图 1.5更新视图 1.6视图使用规则 1.7修改视图 1.8删除视图 2.索引 2.1什么是索引 2.2索引特点 2.3索引分类 2.4索引优缺点 2.5创建索引 2.6查看索引 2.7删除索引 1.视图 1.1什么是…

go中map

文章目录 Map简介哈希表与Map的概念Go语言内建的Map类型Map的声明Map的初始化Map的访问Map的添加和修改Map的删除Map的遍历 Map的基本使用Map的声明与初始化Map的访问与操作Map的删除Map的遍历Map的并发问题实现线程安全的Map 3. Map的访问与操作3.1 访问Map元素代码示例&#…

释疑 803-(1)概述 精炼提纯版

目录 习题 1-01计算机网络可以向用户提供哪些服务? 1-02 试简述分组交换的要点。 1-03 试从多个方面比较电路交换、报文交换和分组交换的主要优缺点。 1-05 互联网基础结构的发展大致分为哪几个阶段?请指出这几个阶段最主要的特点。 1-06 简述互联网标准制定的几个阶段…

web网站组成

web网站由四部分组成&#xff1a;浏览器 前端服务器 后端服务器 数据库服务器 流程&#xff1a; 1.浏览器输入网站后&#xff0c;向前端服务器发送请求&#xff0c;前端服务器响应&#xff0c;静态的数据给浏览器。 2.前端代码中script中有url,这个是向后台发送请求的网…

手撕数据结构---------顺序表和链表

1.线性表 线性表&#xff08;linear list&#xff09;是n个具有相同特性的数据元素的有限序列。 线性表是⼀种在实际中⼴泛使 ⽤的数据结构&#xff0c;常⻅的线性表&#xff1a;顺序表、链表、栈、队列、字符串… 线性表在逻辑上是线性结构&#xff0c;也就说是连续的⼀条直…

Python研究生毕业设计,数据挖掘、情感分析、机器学习

最近在学校毕业了&#xff0c;其中有很多毕业论文使用到的代码&#xff0c;如数据挖掘、情感分析、机器学习、数据预测处理、划分数据集和测试集&#xff0c;绘制分类任务&#xff0c;词汇表示&#xff1a;使用TF-IDF向量化器&#xff0c;线性回归、多元线性回归、SVR回归模型&…

ecshop网站部署

目录 步骤1 ecshop网站的部署 一、安装环境 二、设置开机启动 ​三、 测试php ​四、上传安装包 五、安装ecshop 步骤1 ecshop网站的部署 一、安装环境 yum install -y httpd mariadb-server php php-devel php-mysql 浏览器访问&#xff1a;192.168.30.2 二、设置开机启…

LeetCode 415.字符串相加 C++写法

LeetCode 415.字符串相加 C写法 思路&#x1f914;&#xff1a; 首先不能用stoi和tostring来做&#xff0c;如果给一个很大的数那一定存不下。我们可以从后往前一位一位的取&#xff0c;创建一个变量存储进位用于计算下一位数&#xff0c;之后取模得到当前数字&#xff0c;每一…

k8s部署rabbitmq集群

1 部署集群 1.1 安装 # 创建一个中间件的命名空间 kubectl create namespace middleware # 创建ConfigMap,包含RabbitMQ的配置文件内容 kubectl apply -f rabbitmq-configmap.yaml # 配置用于存储RabbitMQ数据的PersistentVolume&#xff08;PV&#xff09;和PersistentVolum…

iPhone 17系列取消17 Plus版本?新一代苹果手机迎来新变革

随着科技的飞速发展&#xff0c;苹果公司再次准备刷新我们的期待&#xff0c;即将推出的iPhone 17系列携带着一系列令人兴奋的升级。今年&#xff0c;苹果打破了常规&#xff0c;将四款新机型带入市场——iPhone 17、17 Pro、17 Pro Max&#xff0c;以及一款全新的成员&#xf…

Java开发之反射与动态代理

#来自ゾフィー&#xff08;佐菲&#xff09; 1 反射&#xff08;Reflect&#xff09; 运行期间&#xff0c;获取类的信息&#xff0c;进行一些操作。 运行时构造类的对象。运行时获取类的成员变量和方法。运行时调用对象的方法&#xff08;属性&#xff09;。 2 Class 类 Cla…