QT-------------多线程
实现思路
- QThread 类简介:
QThread
是 Qt 中用于多线程编程的基础类。可以通过继承QThread
并重写run()
方法来创建自定义的线程逻辑。- 新线程的执行从
run()
开始,调用start()
方法启动线程。
- 掷骰子的多线程应用程序:
- 创建一个
DiceThread
类继承自QThread
,在run()
方法中模拟掷骰子操作,并通过信号将结果发送出去。
- 创建一个
- 线程同步:
- 线程同步的概念:确保多个线程之间协调操作,避免数据竞争和不一致性。
- 基于互斥量的线程同步:使用
QMutex
确保在同一时间只有一个线程可以访问共享资源。 - 基于读写锁的线程同步:使用
QReadWriteLock
,允许多个读线程同时访问资源,但写线程独占资源。 - 基于条件等待的线程同步:使用
QWaitCondition
与QMutex
结合,允许线程等待某个条件满足。 - 基于信号量的线程同步:使用
QSemaphore
控制对资源的访问数量。
代码示例
1. QThread 类简介和掷骰子的多线程应用程序
#include <QtWidgets/QApplication>
#include <QtCore/QThread>
#include <QtCore/QRandomGenerator>
#include <QtCore/QDebug>
#include <QtCore/QMutex>
#include <QtCore/QReadWriteLock>
#include <QtCore/QWaitCondition>
#include <QtCore/QSemaphore>class DiceThread : public QThread {Q_OBJECT
signals:void resultReady(int result);protected:void run() override {while (!isInterruptionRequested()) {int diceValue = QRandomGenerator::global()->bounded(1, 7);emit resultReady(diceValue);msleep(1000);}}
};int main(int argc, char *argv[]) {QApplication app(argc, argv);DiceThread diceThread;QObject::connect(&diceThread, &DiceThread::resultReady, [](int result) {qDebug() << "Dice result: " << result;});diceThread.start();// 运行一段时间后停止线程QThread::sleep(10);diceThread.requestInterruption();diceThread.wait();return app.exec();
}#include "main.moc"
2. 基于互斥量的线程同步
#include <QtWidgets/QApplication>
#include <QtCore/QThread>
#include <QtCore/QRandomGenerator>
#include <QtCore/QDebug>
#include <QtCore/QMutex>class SharedData {
public:int value = 0;QMutex mutex;
};class IncrementThread : public QThread {
public:IncrementThread(SharedData *data) : data(data) {}protected:void run() override {for (int i = 0; i < 1000; ++i) {data->mutex.lock();++data->value;data->mutex.unlock();msleep(1);}}private:SharedData *data;
};int main(int argc, char *argv[]) {QApplication app(argc, argv);SharedData sharedData;IncrementThread thread1(&sharedData);IncrementThread thread2(&sharedData);thread1.start();thread2.start();thread1.wait();thread2.wait();qDebug() << "Final value: " << sharedData.value;return app.exec();
}#include "main.moc"
3. 基于读写锁的线程同步
#include <QtWidgets/QApplication>
#include <QtCore/QThread>
#include <QtCore/QRandomGenerator>
#include <QtCore/QDebug>
#include <QtCore/QReadWriteLock>class SharedData {
public:int value = 0;QReadWriteLock lock;
};class ReadThread : public QThread {
public:ReadThread(SharedData *data) : data(data) {}protected:void run() override {for (int i = 0; i < 1000; ++i) {data->lock.lockForRead();qDebug() << "Read value: " << data->value;data->lock.unlock();msleep(1);}}private:SharedData *data;
};class WriteThread : public QThread {
public:WriteThread(SharedData *data) : data(data) {}protected:void run() override {for (int i = 0; i < 100; ++i) {data->lock.lockForWrite();++data->value;data->lock.unlock();msleep(10);}}private:SharedData *data;
};int main(int argc, char *argv[]) {QApplication app(argc, argv);SharedData sharedData;ReadThread reader1(&sharedData);ReadThread reader2(&sharedData);WriteThread writer(&sharedData);reader1.start();reader2.start();writer.start();reader1.wait();reader2.wait();writer.wait();qDebug() << "Final value: " << sharedData.value;return app.exec();
}#include "main.moc"
4. 基于条件等待的线程同步
#include <QtWidgets/QApplication>
#include <QtCore/QThread>
#include <QtCore/QRandomGenerator>
#include <QtCore/QDebug>
#include <QtCore/QMutex>
#include <QtCore/QWaitCondition>class SharedData {
public:int value = 0;QMutex mutex;QWaitCondition condition;bool ready = false;
};class ProducerThread : public QThread {
public:ProducerThread(SharedData *data) : data(data) {}protected:void run() override {QRandomGenerator gen;for (int i = 0; i < 10; ++i) {QThread::msleep(1000);data->mutex.lock();data->value = gen.bounded(1, 100);data->ready = true;data->condition.wakeOne();data->mutex.unlock();}}private:SharedData *data;
};class ConsumerThread : public QThread {
public:ConsumerThread(SharedData *data) : data(data) {}protected:void run() override {while (true) {data->mutex.lock();if (!data->ready) {data->condition.wait(&data->mutex);}qDebug() << "Consumed value: " << data->value;data->ready = false;data->mutex.unlock();}}private:SharedData *data;
};int main(int argc, char *argv[]) {QApplication app(argc, argv);SharedData sharedData;ProducerThread producer(&sharedData);ConsumerThread consumer(&sharedData);consumer.start();producer.start();return app.exec();
}#include "main.moc"
5. 基于信号量的线程同步
#include <QtWidgets/QApplication>
#include <QtCore/QThread>
#include <QtCore/QRandomGenerator>
#include <QtCore/QDebug>
#include <QtCore/QSemaphore>class SharedResource {
public:QSemaphore semaphore;void useResource() {semaphore.acquire();qDebug() << "Using resource...";QThread::msleep(100);semaphore.release();}
};class UserThread : public QThread {
public:UserThread(SharedResource *resource) : resource(resource) {}protected:void run() override {for (int i = 0; i < 10; ++i) {resource->useResource();}}private:SharedResource *resource;
};int main(int argc, char *argv[]) {QApplication app(argc, argv);SharedResource resource;resource.semaphore.release(3);UserThread thread1(&resource);UserThread thread2(&resource);UserThread thread3(&resource);thread1.start();thread2.start();thread3.start();thread1.wait();thread2.wait();thread3.wait();return app.exec();
}#include "main.moc"
代码解释
1. QThread 类简介和掷骰子的多线程应用程序
- DiceThread 类:
- 继承
QThread
并在run()
中模拟掷骰子操作,使用QRandomGenerator
生成 1 到 6 的随机数。 - 通过
resultReady
信号将结果发送出去,在主线程中连接该信号并打印结果。
- 继承
2. 基于互斥量的线程同步
- SharedData 类:
- 包含一个
value
变量和QMutex
。
- 包含一个
- IncrementThread 类:
- 每次循环对
value
加 1 前先加锁,加 1 后解锁,确保同一时间只有一个线程修改value
。
- 每次循环对
3. 基于读写锁的线程同步
- SharedData 类:
- 包含一个
value
变量和QReadWriteLock
。
- 包含一个
- ReadThread 类:
- 读线程使用
lockForRead()
锁定,读取value
后解锁。
- 读线程使用
- WriteThread 类:
- 写线程使用
lockForWrite()
锁定,修改value
后解锁,写线程独占资源,读线程可同时读。
- 写线程使用
4. 基于条件等待的线程同步
- SharedData 类:
- 包含
value
、QMutex
、QWaitCondition
和ready
标志。
- 包含
- ProducerThread 类:
- 生产者线程生成数据,使用
wakeOne()
唤醒等待的消费者。
- 生产者线程生成数据,使用
- ConsumerThread 类:
- 消费者线程等待
ready
标志,使用wait()
等待,一旦有数据可用,打印并重置ready
。
- 消费者线程等待
5. 基于信号量的线程同步
- SharedResource 类:
- 包含
QSemaphore
,初始释放 3 个资源。
- 包含
- UserThread 类:
- 每次使用资源前先
acquire()
资源,使用后release()
资源,确保最多 3 个线程同时使用资源。
- 每次使用资源前先
使用说明
- 对于每个示例,将代码保存为
main.cpp
文件。 - 确保
.pro
文件包含QT += core widgets
以及CONFIG += c++11
。 - 编译并运行程序,观察不同线程同步机制的效果。
相关文章:

QT-------------多线程
实现思路 QThread 类简介: QThread 是 Qt 中用于多线程编程的基础类。可以通过继承 QThread 并重写 run() 方法来创建自定义的线程逻辑。新线程的执行从 run() 开始,调用 start() 方法启动线程。 掷骰子的多线程应用程序: 创建一个 DiceThre…...

【JVM】深入了解Java虚拟机-------内存划分、类加载机制、垃圾回收机制
目录 什么是JVM? 内存划分: 1.堆 (共享) 2.栈 (私有) 3.元数据区(共享) 4.程序计数器(私有) 示例: JVM 类加载 一.类加载过程 1.加载 2.验证 3.…...

k8s部署juicefs
操作系统k8smysqlminiojuicefs内核centos8.21.19.18.0.39RELEASE.2023-12-20T01-00-02Zv0.19.04.18.0-193.el8.x86_64 本文k8s较老采用老版本的juicefs,中间件也都是部署在k8s上。测试是否能成功创建动态pvc挂在到测试pod当中并查看到数据信息。一些偏理论知识就不多…...

【ArcGIS微课1000例】0136:制作千层饼(DEM、影像、等高线、山体阴影图层)
文章目录 一、效果展示二、数据准备三、制作过程1. 打开软件2. 制作DEM图层3. 制作影像层4. 制作TIN层5. 制作等高线层四、注意事项一、效果展示 二、数据准备 订阅专栏后,从专栏配套案例数据包中的0136.rar中获取。 1. dem 2. 影像 3. 等高线 4. tin 三、制作过程 1. 打开软…...

Ajax数据爬取
有时我们用requests 抓取页面得到的结果,可能和在浏览器中看到的不一样:在浏览器中可以看到正常显示的页面数据,而使用requests 得到的结果中并没有这些数据。这是因为 requests 获取的都是原始 HTML 文档,而浏览器中的页面是JavaScript 处理…...

快速上手大模型的对话生成
本项目使用0.5B小模型,结构和大模型别无二致,以方便在如CPU设备上快速学习和上手大模型的对话上传 #mermaid-svg-Z86hUiQZ0hg9BVji {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-Z86hUiQZ0h…...

DateTimeExtensions:一个轻量C#的开源DateTime扩展方法库
推荐一个专门为System.DateTime编写的扩展方法库。 01 项目简介 该项目主要是为System.DateTime和System.DateTimeOffset的编写的扩展方法,包括自然日期差值的文本表示(精确和人性化四舍五入)、多个时区的节假日和工作日计算。 核心扩展方…...

题解:监控屏幕调整问题
问题描述 Reca 公司生产高端显示器,其中最受欢迎的型号是 AB999。屏幕尺寸为 $x \times y$ 的比例。由于某些生产特性,屏幕参数总是整数。最终,屏幕边长比例 $x:y$ 需要适应用户的需求。 为了满足用户需求,公司需要调整屏幕尺寸…...

C语言----指针
目录 1.概念 2.格式 3.指针操作符 4.初始化 1. 将普通变量的地址赋值给指针变量 a. 将数组的首地址赋值给指针变量 b. 将指针变量里面保存的地址赋值给另一个指针变量 5.指针运算 5.1算术运算 5.2 关系运算 指针的大小 总结: 段错误 指针修饰 1. con…...

树莓派之旅-在wsl-x86-64 上进行树莓派的交叉编译
前情提要: 想把自己花里胡哨的终端丢到树莓派上去,可是树莓派算力不够,编译时间过于漫长 交叉编译 定义网上有,懒得复制了,大概就是在本机电脑上编译目标平台的可执行文件 这里的目标平台是树莓派 使用 uname -m …...

nature reviews genetics | 需要更多的针对不同种族的癌症基因组图谱研究,促进精准治疗和维护治疗公平权益
–https://doi.org/10.1038/s41576-024-00796-w Genomic landscape of cancer in racially and ethnically diverse populations 研究团队和单位 Ulrike Peters–Public Health Sciences Division, Fred Hutchinson Cancer Center Claire E. Thomas–Public Health Scienc…...

代码随想录算法训练营day18
代码随想录算法训练营 —day18 文章目录 代码随想录算法训练营前言一、530.二叉搜索树的最小绝对差递归法迭代法 二、501.二叉搜索树中的众数普通二叉树的方法递归法中序迭代法 三、 236. 二叉树的最近公共祖先递归法 总结 前言 今天是算法营的第18天,希望自己能够…...

Kafka安全优化文档:漏洞修复到安全加固
文章目录 1.1.漏洞修复1.1.1.Apache Kafka反序列化漏洞1.1.2.pm2-kafka代码执行漏洞1.1.3.Apache Kafka安全绕过漏洞1.1.4.Apache Kafka Distribution - Schema Repository跨站请求伪造漏洞1.1.5.Apache Kafka输入验证错误漏洞的补丁1.1.6.Apache Kafka信息泄露漏洞1.1.7.Apach…...

Markdown如何添加任务列表-复选框的添加
Markdown如何添加任务列表-复选框的添加 前言语法讲解使用场景及应用实例代码整和渲染结果小结其他文章快来试试吧☺️ Markdown如何添加任务列表-复选框的添加👈点击这里也可查看 前言 To-do任务列表是一种很常见的时间管理工具,它适用于工作计划&…...

基于下垂控制的构网变换器功率控制【微电网变流器】【Simulink】
目录 主要内容 理论研究 整体模型 PQ计算模块 功率控制模块 PWM反馈模块 结果一览 下载链接 主要内容 该仿真针对微电网中分布式电源接入后产生的谐波影响,除了污染网络外,还会恶化微电网变流器输出电流,为了消除谐波影响&a…...

AI定义汽车/跨域融合/整车智能,汽车智能化2.0时代新机会来了
汽车智能化2.0,产业正在发生深度变革。 一方面,AI大模型开始在多个域同步赋能智能汽车,从智能座舱到智能驾驶,再到底盘域,AI大模型正在快速推动汽车变革为超级智能体,AI定义汽车时代开始来临。 另一方面&…...

(leetcode算法题)10. 正则表达式匹配
10. 正则表达式匹配 - 力扣(LeetCode) 此题的要求一个字符串 s 和一个字符规律 p之间支持 . 和 * 的正则表达式匹配 . 匹配任意单个字符 * 匹配零个或多个前面的那一个元素 所谓匹配,是要涵盖 整个 字符串 s 的,而不是部分字符串…...

SpringCloudAlibaba实战入门之Sentinel服务降级和服务熔断(十五)
一、Sentinel概述 1、Sentinel是什么 随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。 一句话概括:sentinel即Hystrix的替代品,官网: https://sentinelguard.io/zh…...

使用爬虫技术获取网页中的半结构化数据
目录 前言1. 半结构化数据与爬虫技术简介1.1 半结构化数据的定义与特性1.2 爬虫技术的基本原理 2. 爬取半结构化数据的实现过程2.1 明确目标与准备2.2 发送HTTP请求2.3 解析网页内容2.4 动态内容的处理2.5 数据存储与清洗 3. 技术挑战与应对策略3.1 处理反爬机制3.2 提高爬取效…...

2025/1/1 路由期末复习作业二
呼呼呼祝大家元旦节快乐啦!(我顶着我超重的黑眼圈说) 昨天一个人在寝室一边吃泡面,一边看步步惊心,一边吃一边哭呜呜呜呜呜若曦为什么不和八爷在一起好好爱,就因为他不当皇帝蛮!难测最是帝王心…...

OpenCV-Python实战(13)——图像轮廓
一、找轮廓 cv2.findContours() contours,hierarchy cv2.findContours(image*,mode*,method*) contours:找到的所有轮廓数组,数组内的元素为轮廓像素点坐标。 hierarchy:轮廓间的层次关系。 image:二值图像(cv2.t…...

javascript变量
变量 命名规范 以 字母、数字、下划线、美元符号 $ 组成、不能以 数字开头、且不能使用 js 中的关键字。 命名规范推荐采用小驼峰 命名法 。类名 采用 大驼峰命名。 var 声明变量的特点 在 script 上下文中定义的是 全局变量,全局变量会自动称为 window的属性。 在…...

在K8S中,如何查看kubelet组件的日志?
在kubernetes中,查看Kubelet组件的日志可以通过几种不同的方法。以下是详细的步骤: 1. 使用journalctl命令: 如果kubelet是通过systemd方式部署,你可以使用journalctl命令来查看其日志。执行journalctl -u kubelet将显示Kubelet…...

android studio android sdk下载地址
android studio安装后,因为公司网络原因,一直无法安装android sdk 后经过手机网络,安装android sdk成功如下,也可以手动下载后指定android sdk本地目录 https://dl.google.com/android/repository/source-35_r01.zip https://dl…...

Fetch处理大模型流式数据请求与解析
为什么有的大模型可以一次返回多个 data? Server-Sent Events (SSE):允许服务器连续发送多个 data: 行,每个代表一个独立的数据块。 流式响应:大模型服务通常以流式响应方式返回数据,提高响应速度。 批量处理&#x…...

FPGA自学之路:到底有多崎岖?
FPGA,即现场可编程门阵列,被誉为硬件世界的“瑞士军刀”,其灵活性和可编程性让无数开发者为之倾倒。但谈及FPGA的学习难度,不少人望而却步。那么,FPGA自学之路到底有多崎岖呢? 几座大山那么高?…...

从0到机器视觉工程师(二):封装调用静态库和动态库
目录 静态库 编写静态库 使用静态库 方案一 方案二 动态库 编写动态库 使用动态库 方案一 方案二 方案三 总结 静态库 静态库是在编译时将库的代码合并到最终可执行程序中的库。静态库的优势是在编译时将所有代码包含在程序中,可以使程序独立运行&…...

[极客大挑战 2019]Knife1
这里很显然,根据提示可以猜测,已经有一句话木马上传了,但是路径这里不是很清楚,不知道路径在哪里,不过还是用菜刀连一下试试: 连接成功,在根目录下发现flag。不过如果不用菜刀,可以用…...

【在Python中生成随机字符串】
在Python中生成随机字符串,你可以结合使用random模块和字符串操作。以下是一个常用的方法,通过从预定义的字符集中随机选择字符来构建字符串: import random import stringdef generate_random_string(length):# 定义字符集:可以…...

【three.js】场景搭建
three.js由场景、相机、渲染器、灯光、控制器等几个要素组成。每个要素都有不同的类型,例如光照有太阳光、环境光、半球光等等。每种光照都有不同的属性可以进行配置。 场景 场景(scene):场景是所有物体的容器,如果要…...