基于Qt的信号量的使用

news/2025/3/12 21:05:21/文章来源:https://www.cnblogs.com/mengxiangdu/p/18764678

下面是用两个线程,一个是生产者不断地产生数据,另一个则不断消耗数据。这个例子可以很好的演示生产者/消费者模型。由于C++在C++20之后才提供信号量类型,所以这里的测试环境是Qt5.9和VS2019。

Misc.h文件:

#pragma once#include <qsemaphore.h>
#include <qthread.h>
#include "qvector.h"class MData
{
public:MData(int imaxCount, int iblock);template<typename Func>void customer(Func func);template<typename Func>void producer(Func func);int blockSize() const;int count() const;quint8& operator[](int index);const quint8& operator[](int index) const;private:QSemaphore myAvailable; /* 多少可用的资源 */QSemaphore myLeft; /* 剩余多少空位置 */QVector<quint8> buffer;int maxCount;int eachSize;
};class MProduce : public QThread
{Q_OBJECTpublic:MProduce(MData* idata, QObject* parent = 0);void quit();private:void run() override;private:MData* data;int currBlock;bool running;
};class MCustom : public QThread
{Q_OBJECTpublic:MCustom(MData* idata, QObject* parent = 0);void quit();private:void run() override;private:MData* data;int currBlock;bool running;
};
View Code

Misc.cpp文件:

MData::MData(int imaxCount, int iblock) :myAvailable(0), myLeft(imaxCount),buffer(imaxCount* iblock, 0)
{maxCount = imaxCount;eachSize = iblock;
}template<typename Func>
bool MData::customer(Func func)
{bool result = myAvailable.tryAcquire(1, 1000);if (result) /* 设置超时,这样在没有数据的时候线程可以退出 */{func(*this);myLeft.release();}return result;
}template<typename Func>
void MData::producer(Func func)
{myLeft.acquire();func(*this);myAvailable.release();
}int MData::blockSize() const
{return eachSize;
}int MData::count() const
{return maxCount;
}quint8& MData::operator[](int index)
{return buffer[index];
}const quint8& MData::operator[](int index) const
{return buffer[index];
}MProduce::MProduce(MData* idata, QObject* parent) :QThread(parent)
{data = idata;currBlock = 0;running = true;
}void MProduce::quit()
{running = false;
}void MProduce::run()
{while (running){data->producer([this](MData& d) {int size = d.blockSize();for (int i = 0; i < size; i++){d[currBlock * size + i] = qrand(); // 往里面填充随机数
            }});currBlock = (currBlock + 1) % data->count();}
}MCustom::MCustom(MData* idata, QObject* parent) :QThread(parent)
{data = idata;currBlock = 0;running = true;
}void MCustom::quit()
{running = false;
}void MCustom::run()
{while (running){bool succeed = data->customer([this](MData& d) {int size = d.blockSize();qDebug() << u8"大小" << size << u8"已消耗";});if (succeed) // 消耗成功才向后移动数据
        {currBlock = (currBlock + 1) % data->count();}}
}

 在主函数中使用。我是在QtWidget环境下测试的所以没有控制台输出而是用qDebug()输出数据:

void main()
{MData* data = new MData(3, 1024); // 分配3个1KB的容器装数据MProduce produce(data, this);MCustom custom(data, this);qDebug() << u8"已启动";custom.start();produce.start();QThread::msleep(3000);qDebug() << u8"已停止生产者";produce.quit();produce.wait();QThread::msleep(3000);custom.quit();custom.wait();qDebug() << u8"已停止消费者";delete data;
}

在VS2019的调试窗口的输出文本如下。从输出中可以看到在“停止生产者”之前输出的数据非常多,说明系统可以连续运行。而在“停止生产者”之后,只输出个别的数据就停止了,这符合停止生产者的设定。消费者只消耗生产者生产的剩余数据就停了,然后在超时后退出线程。

已启动
大小 1024 已消耗
...
大小 1024 已消耗
大小 1024 已消耗
大小 1024 已消耗
已停止生产者
大小 1024 已消耗
线程 0xf7d8 已退出,返回值为 0 (0x0)。
线程 0x7450 已退出,返回值为 0 (0x0)。
已停止消费者

 

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

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

相关文章

linux 中awk命令删除指定字段中特定字符串前边所有内容

001、删除第9个字段gene_id前边的所有内容[b20223040323@admin2 test]$ ls a.txt [b20223040323@admin2 test]$ cat a.txt ## 测试数据 NC_089035.1 Gnomon transcript 7328 15219 . + . transcript_id "rna-XM_015766610.3&quo…

.NET Core 中如何实现缓存的预热?

在构建高性能的 .NET Core 应用时,缓存是提升系统响应速度、减轻数据库压力的利器。然而,缓存并非一蹴而就,它也需要“热身”才能发挥最佳性能。这就是缓存预热的意义所在。 一、什么是缓存预热? 缓存预热,顾名思义,就是在系统启动或缓存失效后,主动将热点数据加载到缓存…

EtherNet/IP转PROFINET网关模块促成罗克韦尔PLC与变频器协议互通

一、案例背景在某新能源汽车电池生产线上,需要将采用EtherNet/IP协议的电池检测设备与采用ProfiNet协议的生产线控制系统进行集成,以实现对电池生产过程的全面监控和数据采集。 二、硬件设备西门子S7-1500 PLC 新能源电池容量测试仪:支持标准的EtherNet/IP协议 捷米特捷米特…

Modbus转PROFINET网关模块让Modbus上位机与电机高效通讯

某汽车零部件制造企业的生产线,其自动化设备来自不同品牌和供应商,如汽车生产线的总控制系统采用Modbus TCP协议,它是整个生产线的主站,而部分生产设备如汇川的伺服电机和欧姆龙的仪表等采用Profinet协议,作为从站,这时候需要Modbus TCP协议设备与Profinet协议设备进行通…

No.52 ES6---Promise对象

一、Promise对象 1.1基本概念Promise 是异步编程的一种解决方案,比传统的解决方案--回调函数和事件----更合理和更强大。 它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise 对象。 所谓 promise,简单说就是一个容器,里面保存着某个未来才会结…

类型转换+变量+常量+作用域

类型转换+变量+常量+作用域强制转换 (类型)变量名 高-->低 自动转化 低-->高 注意点不能对布尔值进行转换 不能把对象类型转换为不相干的类型 在把高容量转换到低容量的时候,强制转换 转换的时候可能存在内存溢出,或者精度问题变量变量作用域常量

ITSM流程落地经验之变更管理

本文来自腾讯蓝鲸智云社区用户: CanWay大多数组织中都实施了变更管理,但是效果参差不齐,尤其在变更管理的核心环节,部分组织因缺乏有效的把控,使得变更管理的效果不尽人意,甚至可能面临失控的风险。为此,我们有必要深入探讨并详细分析变更管理中的关键活动,并通过实例加…

国货国用信创在教育领域的应用

信创,即信息技术应用创新产业,旨在实现信息技术领域的自主可控,减少对国外技术的依赖,保障国家信息安全。在教育领域,国货国用信创的应用正逐渐改变着传统的教育模式,为教育的现代化发展注入新的活力。随着科技的飞速发展,教育领域也面临着数字化转型的迫切需求。信创产…

信创概念十大龙头股的风险与机遇深度剖析

信创,即信息技术应用创新产业,旨在实现信息技术领域的自主可控,减少对国外技术的依赖,保障国家信息安全。近年来,随着国家政策的大力支持和科技发展的需求,信创概念逐渐兴起,相关企业迎来了前所未有的发展机遇。在信创概念板块中,有十大龙头股备受关注,它们在行业中具…

易基因:中农大曾祥芳团队WGBS+ChIP-seq揭示蛋氨酸在母胎免疫耐受和子宫内膜容受中的表观调控机制|Cell Rep

大家好,这里是专注表观组学十余年,领跑多组学科研服务的易基因。 母胎免疫耐受是指母体免疫系统对胎儿抗原的耐受,避免对胎儿产生免疫排斥反应。子宫内膜容受性是指子宫内膜接受胚胎着床的能力。子宫内膜容受性和母胎免疫耐受是成功妊娠的两个关键过程。然而,营养所涉及的分…

【文章】更新说明

重要 以后文章优先发布于公众号:瓜穷网络安全团队,请大家关注公众号。本文来自博客园,作者:aoaoaoao,转载请注明原文链接:https://www.cnblogs.com/websecyw/p/18764593

牛客题解 | 迷宫寻路

牛客题库题解题目 题目链接 题解 难度:偏难 知识点:BFS 状态压缩 队列 思路: 如果不存在钥匙和锁的情况:(理解BFS过程) (将例子中的小写字母看为1,大写字母看为0)构成数组G[5][5]起始位置G[0][1],因此得到b[0][1]=0【注】辅助数组b[i][j]用来记录从起始位置到坐标(i…