C++使用开源ConcurrentQueue库处理自定义业务数据类
ConcurrentQueue开源库介绍
ConcurrentQueue是一个高性能的、线程安全的并发队列库。它旨在提供高效、无锁的数据结构,适用于多线程环境中的数据交换。concurrentqueue 支持多个生产者和多个消费者,并且提供了多种配置选项来优化性能和内存使用。
ConcurrentQueue使用
0x01 使用场景说明
我的数据平台在接收到四种不同的业务数据时,需要按数据分类写进RocketMQ。
0x02 自定义类用来存放和区分数据流
- 设计BusinessFlowMsg
- 该类有定义消息的类型
- 该类中设计ST_BusinessSign结构体消息头,用来区分消息和获取消息体的长度
- 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是一个高性能的、线程安全的并发队列库。它旨在提供高效、无锁的数据结构,适用于多线程环境中的数据交换。concurrentqueue 支持多个生产者和多个消费者,并且提供了多种配置选项来优化性能和内存使用。 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"}}}} } 备注:…...
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.虚幻引擎性能优化 (附0跳转Unity对应机制) hard reference and soft reference 1. 硬引用(Hard Reference) 2. 软引用(Soft Reference) 3. 使用原则 2.空间梯度转法线 DDX DDY节点 编辑 …...
macOS 应用公证指南:使用 fastlane 实现自动化公证流程
背景介绍 在 macOS 系统上,为了保护用户安全,Apple 要求开发者对未通过 Mac App Store 分发的应用程序进行公证(Notarization)。如果应用程序没有经过公证,用户在运行时会看到警告弹窗,这会影响用户体验。虽然开启沙箱模式的应用可以直接通过 App Store 分发来避免这个问题…...
深度学习:解密图像、音频和视频数据的“理解”之道20241105
🔍 深度学习:解密图像、音频和视频数据的“理解”之道 深度学习已然成为人工智能领域的中流砥柱,它如何处理不同类型的数据(如图像、音频、视频)?如何将这些数据转换成计算机能理解和学习的“语言”&#…...
uniapp 实现瀑布流
效果演示 组件下载 瀑布流布局-waterfall - DCloud 插件市场...
计算机毕业设计 | springboot+vue智慧工地管理系统 前后端分离后台管理(附源码+文档)
1,项目介绍 管理信息是重要的资源、管理信息是决策的基础。同时管理信息是实施管理控制的依据以及是联系组织内外的纽带。对于企业,最重要的5大资源包括人、物资、能源、资金、信息。人、物资、能源、资金是可以看见的有形资源,信息则是一种…...
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 是否下载默认为下载,传false不…...
Ubuntu下如何管理多个ssh密钥
Ubuntu下如何管理多个ssh密钥 前言 我一直在逃避这个问题,误以为我能够单纯地用一个 ssh 走天下。 好吧,现实是我不得不管理多个 ssh 做,那就写个博客总结一下吧。 查阅后发现前人已经总结了不少,那我就结合之后ÿ…...
[vulnhub] DarkHole: 1
https://www.vulnhub.com/entry/darkhole-1,724/ 端口扫描主机发现 探测存活主机,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…...
商淘云连锁企业管理五大功能 收银系统助力门店进销存同步
连锁企业管理的五大功能相互协作,共同确保连锁门店能够高效运营、降低成本、提升客户满意度,并最终实现盈利目标。今天,商淘云分享连锁企业管理的五大功能: 1、进销存管理:进销存管理是连锁企业的基础功能之一…...
统信UOS开发环境支持Perl
UOS凭借广泛的编程语言支持,为开发者构建了一个高效灵活的开发环境,无需担心环境兼容性问题。 文章目录 一、环境部署1. Perl开发环境安装2. Perl开发环境配置环境变量配置模块管理器编辑器集成调试工具二、代码示例文件处理Web开发三、常见问题1. 依赖管理问题2. 性能问题3.…...
Stable Diffusion Web UI - ControlNet 姿势控制 openpose
openpose 是 ControlNet 中常用的控制模式之一。 通过 openpose 可以锁定人物姿势,把姿势信息传递给 Stable Diffusion 扩散模型,让其在扩散生成图片的时候遵照特定的任务姿势。 通过 openpose 能够得到类似如下效果: 同样的姿势࿰…...
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中处理跨域请求(CORS, Cross-Origin Resource Sharing)通常有几种方法。跨域请求是指从一个域名的网页去请求另一个域名下的资源。为了安全起见,浏览器会阻止这种请求,除非服务器明确允许。 方法一:使用…...
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插入就可以将开发板启动,串口接UART1,进入Lin…...
分布式唯一ID生成(二): leaf
文章目录 本系列前言号段模式双buffer优化biz优化动态step源码走读 雪花算法怎么设置workerId解决时钟回拨源码走读 总结 本系列 漫谈分布式唯一ID分布式唯一ID生成(二):leaf(本文)分布式唯一ID生成(三&am…...
深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)
引言 工欲善其事,必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后,我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集,就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么?它的作用是什么? Spring框架的核心容器是IoC(控制反转)容器。它的主要作用是管理对…...
