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

C++使用开源ConcurrentQueue库处理自定义业务数据类

ConcurrentQueue开源库介绍

ConcurrentQueue是一个高性能的、线程安全的并发队列库。它旨在提供高效、无锁的数据结构,适用于多线程环境中的数据交换。concurrentqueue 支持多个生产者和多个消费者,并且提供了多种配置选项来优化性能和内存使用。

ConcurrentQueue使用

0x01 使用场景说明

我的数据平台在接收到四种不同的业务数据时,需要按数据分类写进RocketMQ。

0x02 自定义类用来存放和区分数据流

  • 设计BusinessFlowMsg
  1. 该类有定义消息的类型
  2. 该类中设计ST_BusinessSign结构体消息头,用来区分消息和获取消息体的长度
  3. BusinessFlowMsg类可以存放的数据长度为512KB
#ifndef BUSINESSFLOWMSG_HPP
#define BUSINESSFLOWMSG_HPP#include <string.h>#define MSG_ROCKETMQ_PNG 0x01
#define MSG_ROCKETMQ_AIS 0x02
#define MSG_ROCKETMQ_ROUTE 0x03
#define MSG_ROCKETMQ_VOYAGE 0x04#pragma pack(push)
#pragma pack(1)// 消息头
typedef struct s_BusinessSign
{int sign; // 业务标识unsigned int length; // 消息体的长度
}ST_BusinessSign;#pragma pack(pop)class BusinessFlowMsg
{
public:BusinessFlowMsg() = default;~BusinessFlowMsg() = default;char* get_data(){return _data;}int data_size(){return businessSign.length;}char* get_body(){return _data + sizeof(ST_BusinessSign);}int body_size(){return data_size() - sizeof(ST_BusinessSign);}ST_BusinessSign* header(){return &businessSign;}bool set_data(const char* data, int length, int sign){if(length > (max_body_len + sizeof(ST_BusinessSign))){return false;}businessSign.sign = sign;businessSign.length = length;memcpy(_data + sizeof(ST_BusinessSign), data, length);return true;}private:enum{max_body_len = 512 * 1024 // 512KB};ST_BusinessSign businessSign;char _data[max_body_len];
};#endif // BUSINESSFLOWMSG_HPP

0x03 创建PngUnit类模拟接到不同的业务数据

  • PngUnit类型创建了四个线程来模拟不同的数据流。
  • PngUnit类多线程中并未使用互斥锁,因为ConcurrentQueue是一个线程安全的并发队列库,事实证明确实如此。
#ifndef PNGUNIT_H
#define PNGUNIT_H#include <thread>
#include <mutex>class PngUnit
{
public:PngUnit();~PngUnit() = default;void start();void sendPNG(int sign);void sendAIS(int sign);void sendRoute(int sign);void sendVoyage(int sign);private:std::thread m_th_png;std::thread m_th_ais;std::thread m_th_route;std::thread m_th_voyage;// std::mutex queue_mutex;  // 互斥锁
};#endif // PNGUNIT_H

#include "pngunit.h"
#include <unistd.h>
#include "rocketmqutils.h"
#include "BusinessFlowMsg.hpp"
#include "json11/json11.hpp"PngUnit::PngUnit()
{}void PngUnit::start()
{// m_th = std::thread([this](){//     sendPNG(100);// });if(m_th_png.joinable()){printf("[%s:%d] %s\n", __FILE__, __LINE__, "m_th_png is running");return;}m_th_png = std::thread(std::bind(&PngUnit::sendPNG, this, MSG_ROCKETMQ_PNG));m_th_ais= std::thread(std::bind(&PngUnit::sendAIS, this, MSG_ROCKETMQ_AIS));m_th_route= std::thread(std::bind(&PngUnit::sendRoute, this, MSG_ROCKETMQ_ROUTE));m_th_voyage= std::thread(std::bind(&PngUnit::sendVoyage, this, MSG_ROCKETMQ_VOYAGE));
}void PngUnit::sendPNG(int sign)
{while (true){BusinessFlowMsg pngMsg;const char* pngFile = "1234567890ABCDEF";int fileLen = strlen(pngFile) + 1;pngMsg.set_data(pngFile, fileLen, sign);{// std::lock_guard<std::mutex> lock(queue_mutex);if(!RocketMQUtils::Instance()->g_businessQueue.enqueue(pngMsg)){printf("Failed to set PNG message data");}}sleep(1);}
}void PngUnit::sendAIS(int sign)
{json11::Json::object obj = {{"message", "AIS"},{"response", "success"}};std::string jsonStr = json11::Json(obj).dump();while (true){BusinessFlowMsg aisMsg;int jsonStrLen = jsonStr.size();aisMsg.set_data(jsonStr.c_str(), jsonStrLen, sign);{// std::lock_guard<std::mutex> lock(queue_mutex);if(!RocketMQUtils::Instance()->g_businessQueue.enqueue(aisMsg)){printf("Failed to set AIS message data");}}sleep(2);}
}void PngUnit::sendRoute(int sign)
{json11::Json::object obj = {{"message", "Route"},{"response", "success"}};std::string jsonStr = json11::Json(obj).dump();while (true){BusinessFlowMsg routeMsg;int jsonStrLen = jsonStr.size();routeMsg.set_data(jsonStr.c_str(), jsonStrLen, sign);{// std::lock_guard<std::mutex> lock(queue_mutex);if(!RocketMQUtils::Instance()->g_businessQueue.enqueue(routeMsg)){printf("Failed to set ROUTE message data");}}sleep(3);}
}void PngUnit::sendVoyage(int sign)
{json11::Json::object obj = {{"message", "Voyage"},{"response", "success"}};std::string jsonStr = json11::Json(obj).dump();while (true){BusinessFlowMsg voyageMsg;int jsonStrLen = jsonStr.size();voyageMsg.set_data(jsonStr.c_str(), jsonStrLen, sign);{// std::lock_guard<std::mutex> lock(queue_mutex);if(!RocketMQUtils::Instance()->g_businessQueue.enqueue(voyageMsg)){printf("Failed to set VOYAGE message data");}}sleep(4);}
}

0x04 创建RocketMQUtils类,在ConcurrentQueue队列中获取数据写进RocketMQ

  • RocketMQUtils类是一个单例类
#ifndef ROCKETMQUTILS_H
#define ROCKETMQUTILS_H#include <thread>
#include <concurrentqueue/moodycamel/concurrentqueue.h>
#include "BusinessFlowMsg.hpp"class RocketMQUtils
{
public:static RocketMQUtils* Instance();private:RocketMQUtils();~RocketMQUtils()=default;RocketMQUtils(const RocketMQUtils &) = delete;RocketMQUtils& operator=(const RocketMQUtils &) = delete;RocketMQUtils(RocketMQUtils &&) = delete;RocketMQUtils& operator=(RocketMQUtils &&) = delete;public:void start();void push();void poll();bool write(char *data, int len, int sign);public:moodycamel::ConcurrentQueue<BusinessFlowMsg> g_businessQueue;private:static RocketMQUtils* _instance;std::thread _pushThread;
};#endif // ROCKETMQUTILS_H

#include "rocketmqutils.h"
#include <unistd.h>RocketMQUtils * RocketMQUtils::_instance = nullptr;RocketMQUtils *RocketMQUtils::Instance()
{if(_instance == nullptr){_instance = new RocketMQUtils();}return _instance;
}RocketMQUtils::RocketMQUtils()
{}void RocketMQUtils::start()
{if(_pushThread.joinable()){return;}_pushThread = std::thread(&RocketMQUtils::push, this);
}void RocketMQUtils::push()
{while (true){BusinessFlowMsg busiMsg;if(g_businessQueue.try_dequeue(busiMsg)){write(busiMsg.get_body(), busiMsg.header()->length, busiMsg.header()->sign);}else{printf("[%s:%d] %s\n", __FILE__, __LINE__, "g_businessQueue is empty");sleep(2);}}
}void RocketMQUtils::poll()
{}bool RocketMQUtils::write(char *data, int len, int sign)
{std::string msg(data, len);if (sign == MSG_ROCKETMQ_PNG){printf("[%s:%d] [%d] %s\n", __FILE__, __LINE__, sign, msg.c_str());}else if (sign == MSG_ROCKETMQ_AIS){printf("[%s:%d] [%d] %s\n", __FILE__, __LINE__, sign, msg.c_str());}else if (sign == MSG_ROCKETMQ_ROUTE){printf("[%s:%d] [%d] %s\n", __FILE__, __LINE__, sign, msg.c_str());}else if (sign == MSG_ROCKETMQ_VOYAGE){printf("[%s:%d] [%d] %s\n", __FILE__, __LINE__, sign, msg.c_str());}else{printf("[%s:%d] data sign error\n", __FILE__, __LINE__);}
}

0x05 使用演示

#include <iostream>
#include <memory>
#include "rocketmqutils.h"
#include "pngunit.h"using namespace std;int main()
{cout << "==Start==" << endl;RocketMQUtils* rocketmq = RocketMQUtils::Instance();rocketmq->start();std::shared_ptr<PngUnit> ptrPngUnit = std::make_shared<PngUnit>();ptrPngUnit->start();getchar();cout << "==Over==" << endl;return 0;
}

在这里插入图片描述

相关文章:

C++使用开源ConcurrentQueue库处理自定义业务数据类

ConcurrentQueue开源库介绍 ConcurrentQueue是一个高性能的、线程安全的并发队列库。它旨在提供高效、无锁的数据结构&#xff0c;适用于多线程环境中的数据交换。concurrentqueue 支持多个生产者和多个消费者&#xff0c;并且提供了多种配置选项来优化性能和内存使用。 Conc…...

在vue3的vite网络请求报错 [vite] http proxy error:

在开发的过程中 代理proxy报错: [vite] http proxy error: /ranking/hostRank?dateType1 Error: connect ETIMEDOUT 43.xxx.xxx.xxx:443 网络请求是http的: // vite.config.ts import { Agent } from node:http;server: {host: 0.0.0.0,port: port,open: true,https: false,…...

ElasticSearch 简单的查询。查询存在该字段的资源,更新,统计

1.查询存在该字段的数据 {"query": {"bool": {"must": [{"exists": { "field": "chainCode"}}],"must_not": {"exists": {"field": "isDelete"}}}} } 备注&#xff1a…...

FOFA使用教程之从零到精通

FOFA使用教程之从零到精通 前言一、关于网络资产测绘的概念1、啥是网络空间资产测绘2、啥是互联网资产二、FOFA的简要介绍1、FOFA地址是啥?2、关于FOFA的简要介绍三、FOFA精讲1、运算符规则详解① 关于 = 号的使用说明② 关于 == 号的使用说明③ 关于 && 号的使用说明…...

【提高篇】3.2 GPIO(二,基本结构)

目录 一,GPIO的基本结构 二,保护二极管 三,上拉、下拉电阻 四,施密特触发器 五,P-MOS 管和 N-MOS 管 P-MOS管和N-MOS管的区别 六,片上外设 七,IDR,ODR,BSRR寄存器 7.1 IDR(Input Data Register) 7.2 ODR(Output Data Register) 7.3 BSRR(Bit Set/Rese…...

UE hard/soft reference| DDX DDY | Unity pcg color

目录 1.虚幻引擎性能优化 &#xff08;附0跳转Unity对应机制&#xff09; hard reference and soft reference 1. 硬引用&#xff08;Hard Reference&#xff09; 2. 软引用&#xff08;Soft Reference&#xff09; 3. 使用原则 2.空间梯度转法线 DDX DDY节点 ​编辑 …...

macOS 应用公证指南:使用 fastlane 实现自动化公证流程

背景介绍 在 macOS 系统上,为了保护用户安全,Apple 要求开发者对未通过 Mac App Store 分发的应用程序进行公证(Notarization)。如果应用程序没有经过公证,用户在运行时会看到警告弹窗,这会影响用户体验。虽然开启沙箱模式的应用可以直接通过 App Store 分发来避免这个问题…...

深度学习:解密图像、音频和视频数据的“理解”之道20241105

&#x1f50d; 深度学习&#xff1a;解密图像、音频和视频数据的“理解”之道 深度学习已然成为人工智能领域的中流砥柱&#xff0c;它如何处理不同类型的数据&#xff08;如图像、音频、视频&#xff09;&#xff1f;如何将这些数据转换成计算机能理解和学习的“语言”&#…...

uniapp 实现瀑布流

效果演示 组件下载 瀑布流布局-waterfall - DCloud 插件市场...

计算机毕业设计 | springboot+vue智慧工地管理系统 前后端分离后台管理(附源码+文档)

1&#xff0c;项目介绍 管理信息是重要的资源、管理信息是决策的基础。同时管理信息是实施管理控制的依据以及是联系组织内外的纽带。对于企业&#xff0c;最重要的5大资源包括人、物资、能源、资金、信息。人、物资、能源、资金是可以看见的有形资源&#xff0c;信息则是一种…...

vue中html如何转成pdf下载,pdf转base64,忽略某个元素渲染在pdf中,方法封装

一、下载 html2Canvas jspdf npm install jspdf html2canvas二、封装转换下载方法 htmlToPdf.js import html2Canvas from html2canvas import JsPDF from jspdf/*** param {*} reportName 下载时候的标题* param {*} isDownload 是否下载默认为下载&#xff0c;传false不…...

Ubuntu下如何管理多个ssh密钥

Ubuntu下如何管理多个ssh密钥 前言 ‍ 我一直在逃避这个问题&#xff0c;误以为我能够单纯地用一个 ssh 走天下。 好吧&#xff0c;现实是我不得不管理多个 ssh 做&#xff0c;那就写个博客总结一下吧。 查阅后发现前人已经总结了不少&#xff0c;那我就结合之后&#xff…...

[vulnhub] DarkHole: 1

https://www.vulnhub.com/entry/darkhole-1,724/ 端口扫描主机发现 探测存活主机&#xff0c;184是靶机 nmap -sP 192.168.75.0/24 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-11-08 09:59 CST Nmap scan report for 192.168.75.1 Host is up (0.00027s latency). MA…...

商淘云连锁企业管理五大功能 收银系统助力门店进销存同步

连锁企业管理的五大功能相互协作&#xff0c;共同确保连锁门店能够高效运营、降低成本、提升客户满意度&#xff0c;并最终实现盈利目标。今天&#xff0c;商淘云分享连锁企业管理的五大功能&#xff1a; 1、进销存管理&#xff1a;进销存管理是连锁企业的基础功能之一&#xf…...

统信UOS开发环境支持Perl

UOS凭借广泛的编程语言支持,为开发者构建了一个高效灵活的开发环境,无需担心环境兼容性问题。 文章目录 一、环境部署1. Perl开发环境安装2. Perl开发环境配置环境变量配置模块管理器编辑器集成调试工具二、代码示例文件处理Web开发三、常见问题1. 依赖管理问题2. 性能问题3.…...

Stable Diffusion Web UI - ControlNet 姿势控制 openpose

openpose 是 ControlNet 中常用的控制模式之一。 通过 openpose 可以锁定人物姿势&#xff0c;把姿势信息传递给 Stable Diffusion 扩散模型&#xff0c;让其在扩散生成图片的时候遵照特定的任务姿势。 通过 openpose 能够得到类似如下效果&#xff1a; 同样的姿势&#xff0…...

java中Json字符串转换

文章目录 map与json互转map转jsonmap形式的json转map list与json互转list转jsonlist形式的json转list map形式的json串中含有列表转列表 map与json互转 map转json JSONObject.toJSONString(map); public static void main(String[] args) {Map<String, Object> map n…...

springboot处理跨域请求

在Spring Boot中处理跨域请求&#xff08;CORS, Cross-Origin Resource Sharing&#xff09;通常有几种方法。跨域请求是指从一个域名的网页去请求另一个域名下的资源。为了安全起见&#xff0c;浏览器会阻止这种请求&#xff0c;除非服务器明确允许。 方法一&#xff1a;使用…...

S32G-VNP-RDB2开发环境搭建

下载官方镜像 刷机 cat /proc/partition or df -lh //查看sdcard卡再/dev目录挂在点 export DEVSD/dev/sdb sudo dd iffsl-image-auto-s32g274ardb2.sdcard of${DEVSD} bs1M && sync以上将SD-card插入就可以将开发板启动&#xff0c;串口接UART1&#xff0c;进入Lin…...

分布式唯一ID生成(二): leaf

文章目录 本系列前言号段模式双buffer优化biz优化动态step源码走读 雪花算法怎么设置workerId解决时钟回拨源码走读 总结 本系列 漫谈分布式唯一ID分布式唯一ID生成&#xff08;二&#xff09;&#xff1a;leaf&#xff08;本文&#xff09;分布式唯一ID生成&#xff08;三&am…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

STM32标准库-DMA直接存储器存取

文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包

文章目录 现象&#xff1a;mysql已经安装&#xff0c;但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时&#xff0c;可能是因为以下几个原因&#xff1a;1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

GruntJS-前端自动化任务运行器从入门到实战

Grunt 完全指南&#xff1a;从入门到实战 一、Grunt 是什么&#xff1f; Grunt是一个基于 Node.js 的前端自动化任务运行器&#xff0c;主要用于自动化执行项目开发中重复性高的任务&#xff0c;例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill

视觉语言模型&#xff08;Vision-Language Models, VLMs&#xff09;&#xff0c;为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展&#xff0c;机器人仍难以胜任复杂的长时程任务&#xff08;如家具装配&#xff09;&#xff0c;主要受限于人…...

【Linux系统】Linux环境变量:系统配置的隐形指挥官

。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量&#xff1a;setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...

Qt 事件处理中 return 的深入解析

Qt 事件处理中 return 的深入解析 在 Qt 事件处理中&#xff0c;return 语句的使用是另一个关键概念&#xff0c;它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别&#xff1a;不同层级的事件处理 方…...

消息队列系统设计与实践全解析

文章目录 &#x1f680; 消息队列系统设计与实践全解析&#x1f50d; 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡&#x1f4a1; 权衡决策框架 1.3 运维复杂度评估&#x1f527; 运维成本降低策略 &#x1f3d7;️ 二、典型架构设计2.1 分布式事务最终一致…...

【FTP】ftp文件传输会丢包吗?批量几百个文件传输,有一些文件没有传输完整,如何解决?

FTP&#xff08;File Transfer Protocol&#xff09;本身是一个基于 TCP 的协议&#xff0c;理论上不会丢包。但 FTP 文件传输过程中仍可能出现文件不完整、丢失或损坏的情况&#xff0c;主要原因包括&#xff1a; ✅ 一、FTP传输可能“丢包”或文件不完整的原因 原因描述网络…...