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

【消息队列开发】 实现内存加载

文章目录

  • 🍃前言
  • 🌳实现思路
    • 🚩读取消息长度
    • 🚩读取相应长度的消息
    • 🚩进行反序列化
    • 🚩判定是否有效
    • 🚩加入有效消息
    • 🚩收尾工作
    • 🚩代码实现
  • ⭕总结

🍃前言

本次开发目标实现内存加载

我们在硬盘与内存中都存入了我们的消息,但是呢,当程序重启后,内存中的消息就会丢失,这时候我们就需要将硬盘中的数据写入内存中

🌳实现思路

首先我们定义两个变量

一个是使用一个LinkedList的数组接收硬盘里面存储的数据。

除此之外我们还定义一个变量currentOffset用来记录我们读写文件的光标

接下来我们开始进行实现,分为5步实现

🚩读取消息长度

根据我们定义存入硬盘的消息结构

先读取最前面的四个字节,这四个字节里面的内容代表的是整个消息的长度
在这里插入图片描述

🚩读取相应长度的消息

构造相应长度的字节数组,进行读取

并且进行判断,实际读取消息的长度是否符合

若不符合,我们需要抛出我们自定义的异常
在这里插入图片描述

🚩进行反序列化

在这里插入图片描述

🚩判定是否有效

我们需要对反序列化后的对象进行判断

若该Message对象已近无效,那么我们就可以直接跳过了

需要注意的是,这时候我们也需要将我们的currentOffset变量进行更新

在这里插入图片描述

🚩加入有效消息

若为有效数据, 则需要把这个 Message 对象加入到链表中. 加入之前还需要填写 offsetBeg 和 offsetEnd

进行计算 offset 的时候, 需要知道当前文件光标的位置的.

而我们的currentOffset变量正记录着我们当前的位置
在这里插入图片描述

🚩收尾工作

由于我们不知道消息有多长,所以我们将上述操作放入一个while(true)的循环里进行读取

但是呢,我们应该怎么判断是否读取结束呢?

其实我们使用读取四个字节的方法readInt()

当后面没有数据时,它便会抛出异常,这里我们利用这个抛出的异常,我们在最后进行捕获,但是呢。

这个抛出的“异常”其实是一个正常的数据

🚩代码实现

// 使用这个方法, 从文件中, 读取出所有的消息内容, 加载到内存中(具体来说是放到一个链表里)
// 这个方法, 准备在程序启动的时候, 进行调用.
// 这里使用一个 LinkedList, 主要目的是为了后续进行头删操作.
// 这个方法的参数, 只是一个 queueName 而不是 MSGQueue 对象. 因为这个方法不需要加锁, 只使用 queueName 就够了.
// 由于该方法是在程序启动时调用, 此时服务器还不能处理请求呢~~ 不涉及多线程操作文件.
public LinkedList<Message> loadAllMessageFromQueue(String queueName) throws IOException, MqException, ClassNotFoundException {LinkedList<Message> messages = new LinkedList<>();try (InputStream inputStream = new FileInputStream(getQueueDataPath(queueName))) {try (DataInputStream dataInputStream = new DataInputStream(inputStream)) {// 这个变量记录当前文件光标.long currentOffset = 0;// 一个文件中包含了很多消息, 此处势必要循环读取.while (true) {// 1. 读取当前消息的长度, 这里的 readInt 可能会读到文件的末尾(EOF)//    readInt 方法, 读到文件末尾, 会抛出 EOFException 异常. 这一点和之前的很多流对象不太一样.int messageSize = dataInputStream.readInt();// 2. 按照这个长度, 读取消息内容byte[] buffer = new byte[messageSize];int actualSize = dataInputStream.read(buffer);if (messageSize != actualSize) {// 如果不匹配, 说明文件有问题, 格式错乱了!!throw new MqException("[MessageFileManager] 文件格式错误! queueName=" + queueName);}// 3. 把这个读到的二进制数据, 反序列化回 Message 对象Message message = (Message) BinaryTool.fromBytes(buffer);// 4. 判定一下看看这个消息对象, 是不是无效对象.if (message.getIsValid() != 0x1) {// 无效数据, 直接跳过.// 虽然消息是无效数据, 但是 offset 不要忘记更新.currentOffset += (4 + messageSize);continue;}// 5. 有效数据, 则需要把这个 Message 对象加入到链表中. 加入之前还需要填写 offsetBeg 和 offsetEnd//    进行计算 offset 的时候, 需要知道当前文件光标的位置的. 由于当下使用的 DataInputStream 并不方便直接获取到文件光标位置//    因此就需要手动计算下文件光标.message.setOffsetBeg(currentOffset + 4);message.setOffsetEnd(currentOffset + 4 + messageSize);currentOffset += (4 + messageSize);messages.add(message);}} catch (EOFException e) {// 这个 catch 并非真是处理 "异常", 而是处理 "正常" 的业务逻辑. 文件读到末尾, 会被 readInt 抛出该异常.// 这个 catch 语句中也不需要做啥特殊的事情System.out.println("[MessageFileManager] 恢复 Message 数据完成!");}}return messages;
}

⭕总结

关于《【消息队列开发】 实现内存加载》就讲解到这儿,感谢大家的支持,欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下

相关文章:

  • 【STL容器】Map使用介绍补充说明
  • MongoDB实战面试指南:常见问题一网打尽
  • 华为配置ISP选路实现报文按运营商转发
  • 【MySQL】锁信息
  • 安装Docker仓库Harbor
  • 自动点名器
  • RockChip Android13 修改U盘挂载目录
  • 【Javaweb】【瑞吉外卖】上传下载实现
  • 使用 Jenkins 管道在 Docker Hub 中构建 Docker 镜像
  • 鸿蒙原生应用再添一批新丁!阿里旗下11款应用、广汽传祺、岚图汽车、零跑汽车、凯翼汽车 入局鸿蒙
  • ES6(三):Iterator、Generator、类的用法、类的继承
  • Kubernetes(k8s第四部分之servers)
  • Hadoop大数据应用:Linux 部署 MapReduce 与 Yarn
  • C语言例:表达式(a=2,3),a+1的值
  • WordPress供求插件API文档:获取市场类型
  • android图片蒙层
  • Apache的基本使用
  • CNN 在图像分割中的简史:从 R-CNN 到 Mask R-CNN
  • es6
  • ES6, React, Redux, Webpack写的一个爬 GitHub 的网页
  • Linux各目录及每个目录的详细介绍
  • react-native 安卓真机环境搭建
  • vue总结
  • 记录一下第一次使用npm
  • 一个JAVA程序员成长之路分享
  • 06-01 点餐小程序前台界面搭建
  • hi-nginx-1.3.4编译安装
  • #、%和$符号在OGNL表达式中经常出现
  • #pragma data_seg 共享数据区(转)
  • #周末课堂# 【Linux + JVM + Mysql高级性能优化班】(火热报名中~~~)
  • $(document).ready(function(){}), $().ready(function(){})和$(function(){})三者区别
  • (22)C#传智:复习,多态虚方法抽象类接口,静态类,String与StringBuilder,集合泛型List与Dictionary,文件类,结构与类的区别
  • (二)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (附源码)计算机毕业设计SSM基于java的云顶博客系统
  • (附源码)小程序 交通违法举报系统 毕业设计 242045
  • (四)搭建容器云管理平台笔记—安装ETCD(不使用证书)
  • (五)c52学习之旅-静态数码管
  • **python多态
  • .NET 4.0中的泛型协变和反变
  • .net core 6 使用注解自动注入实例,无需构造注入 autowrite4net
  • .NET Core 项目指定SDK版本
  • .Net IE10 _doPostBack 未定义
  • .net mvc actionresult 返回字符串_.NET架构师知识普及
  • .NET 依赖注入和配置系统
  • .NetCore实践篇:分布式监控Zipkin持久化之殇
  • .NET框架
  • .net用HTML开发怎么调试,如何使用ASP.NET MVC在调试中查看控制器生成的html?
  • /bin/bash^M: bad interpreter: No such file ordirectory
  • ?php echo $logosrc[0];?,如何在一行中显示logo和标题?
  • [<死锁专题>]
  • [20160902]rm -rf的惨案.txt
  • [BJDCTF 2020]easy_md5
  • [C#7] 1.Tuples(元组)
  • [C#基础]说说lock到底锁谁?
  • [C++] Boost智能指针——boost::scoped_ptr(使用及原理分析)