Qt基于等待条件QWaitCondition实现的任务队列模型示例

核心概念

Qt中的QWaitCondition是一个用于多线程同步的类,允许线程在某些条件满足时唤醒其他等待的线程。它通常与QMutex配合使用,协调线程之间的执行顺序,适用于生产者-消费者模型、任务队列调度等场景。

wait():使当前线程进入等待状态,并释放关联的互斥锁。当条件满足时,线程被唤醒并重新获取锁。
wakeOne():唤醒一个正在等待的线程(按操作系统调度策略选择)。
wakeAll():唤醒所有正在等待的线程。

常见用法

**​线程等待条件:**线程检查条件,若不满足则调用wait()进入等待。
**​条件通知:**另一线程修改条件后,调用wakeOne()或wakeAll()通知等待线程。
**​配合QMutex:**所有条件检查和修改必须在QMutex保护下进行,避免竞态条件。

任务队列描述

**​任务队列:**主线程将任务添加到队列,多个工作线程从队列中获取并执行任务。
**​同步机制:**当队列为空时,工作线程等待;当新任务到达时,唤醒一个线程处理。
**​优雅退出:**支持安全终止所有工作线程。

代码实现

#include <QCoreApplication>
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
#include <QQueue>
#include <QDebug>
#include <functional>// 定义任务类型(使用std::function包装可调用对象)
using Task = std::function<void()>;// 线程安全的任务队列
class TaskQueue {
public:void addTask(const Task& task) {QMutexLocker locker(&m_mutex);m_queue.enqueue(task);m_cond.wakeOne(); // 唤醒一个等待线程}Task getTask() {QMutexLocker locker(&m_mutex);//离开作用域(即析构)时自动对m_mutex解锁// 使用while防止虚假唤醒while (m_queue.isEmpty() && !m_stop) {m_cond.wait(&m_mutex); // 自动释放锁并等待,被唤醒(即wait返回)之后自动对m_mutex重新上锁}if (m_stop) return nullptr; // 终止信号return m_queue.dequeue();}void stop() {QMutexLocker locker(&m_mutex);m_stop = true;m_cond.wakeAll(); // 唤醒所有线程退出}private:QMutex m_mutex;QWaitCondition m_cond;QQueue<Task> m_queue;bool m_stop = false;
};// 工作线程:不断从队列中取任务执行
class Worker : public QThread {
public:Worker(TaskQueue* queue) : m_queue(queue) {}void run() override {while (true) {Task task = m_queue->getTask();if (!task) break; // 收到终止信号task(); // 执行任务}qDebug() << "Worker thread" << QThread::currentThread() << "stopped.";}private:TaskQueue* m_queue;
};int main(int argc, char* argv[]) {QCoreApplication a(argc, argv);// 创建任务队列和4个工作线程TaskQueue queue;QList<Worker*> workers;for (int i = 0; i < 4; ++i) {Worker* worker = new Worker(&queue);worker->start();workers.append(worker);}// 添加10个任务到队列for (int i = 0; i < 10; ++i) {queue.addTask([i]() {qDebug() << "Task" << i << "processed by" << QThread::currentThread();QThread::msleep(100); // 模拟任务耗时});}// 等待所有任务执行完毕QThread::sleep(2);// 停止所有工作线程queue.stop();for (Worker* worker : workers) {worker->wait();delete worker;}qDebug() << "All workers stopped.";return 0;
}

运行代码输出

Task 0 processed by QThread(0x1087708)
Task 3 processed by QThread(0x10879d0)
Task 1 processed by QThread(0x10878d0)
Task 2 processed by QThread(0x1087800)
Task 4 processed by QThread(0x1087800)
Task 5 processed by QThread(0x10878d0)
Task 7 processed by QThread(0x10879d0)
Task 6 processed by QThread(0x1087708)
Task 8 processed by QThread(0x10878d0)
Task 9 processed by QThread(0x1087800)
Worker thread QThread(0x1087708) stopped.
Worker thread QThread(0x10879d0) stopped.
Worker thread QThread(0x1087800) stopped.
Worker thread QThread(0x10878d0) stopped.
All workers stopped.

代码解析

1. ​任务队列(TaskQueue类)​

​线程安全操作:
通过QMutex保护任务队列(m_queue)和停止标志(m_stop)。

条件等待:
getTask()中使用while (m_queue.isEmpty() && !m_stop)防止虚假唤醒。
当队列为空且未收到停止信号时,调用m_cond.wait(&m_mutex)释放锁并等待。

终止机制:
stop()方法设置m_stop = true并通过wakeAll()唤醒所有线程。
工作线程收到nullptr任务时退出循环。

2. ​工作线程(Worker类)​

**​任务循环:**持续调用getTask()获取任务,直到收到终止信号。
**​任务执行:**直接调用task()执行实际逻辑(如I/O操作、计算等)。

3. ​主线程逻辑

**​创建线程池:**启动4个工作线程监听任务队列。
**​动态添加任务:**通过Lambda表达式生成任务,支持任意类型的操作。
​优雅退出:
调用queue.stop()通知所有线程停止。
使用worker->wait()确保线程安全退出后清理资源。

关键特性

**​动态任务分配:**支持任意数量、类型的任务。
**​高效唤醒策略:**wakeOne()确保每次新任务只唤醒一个线程,减少竞争。
**​资源安全:**通过RAII(QMutexLocker)自动管理锁,避免死锁。
**​跨平台:**代码在Windows/Linux/macOS上行为一致。

应用场景扩展

​**Web服务器:**将HTTP请求作为任务分配给线程池处理。
**​批量数据处理:**多个线程并行处理文件、数据库操作。
**​GUI程序后台任务:**保持界面响应性,耗时操作放入任务队列。

通过这种模式,可以轻松实现高并发任务处理,同时避免手动管理线程的复杂性。

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

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

相关文章

(转)Java单例模式(1)

l单例模式的好多&#xff1a;节约了内存&#xff0c;提高了代码的执行效率。

【PCIe 总线及设备入门学习专栏 1.2 -- 访问 PCIe 设备过程】

文章目录 OverviewPCIe 系统软件层次TLP 通用格式配置过程PCIe 设备配置寄存器Type0 Configuration Request配置过程Overview 对于PCIe 设备来说,它与桥的连接直通过两条差分信号,那么当桥下面接入多个PCIe 设备时,它是如何选中某个设备的呢?我面前面一篇文件介绍了 PCI设…

HarmonyOS NEXT组件深度全解:十大核心组件开发指南与实战

文章目录 引言&#xff1a;组件化开发的未来趋势第一章&#xff1a;基础UI组件精要1.1 Button&#xff1a;交互设计的基石1.1.1 多态按钮实现1.1.2 高级特性 1.2 Text&#xff1a;文字渲染的进阶技巧1.2.1 富文本混排1.2.2 性能优化 第二章&#xff1a;布局组件深度解析2.1 Fle…

win11编译pytorch cuda128版本流程

Geforce 50xx系显卡最低支持cuda128&#xff0c;torch cu128 release版本目前还没有释放&#xff0c;所以自己基于2.6.0源码自己编译wheel包。 1. 前置条件 1. 使用visual studio installer 安装visual studio 2022&#xff0c;工作负荷选择【使用c的桌面开发】,安装完成后将…

log4j2中<logger>中没有指定appender的输出

一 优先级 1.1 规则 1.如果一个 <logger> 没有显式配置 appender&#xff0c;Log4j2 会将该日志事件传递给其 父 Logger 的 appender。 2.这种传递行为会一直向上追溯&#xff0c;直到找到配置了 appender 的 Logger&#xff0c;或者到达 Root Logger。 3.如果日志事…

【MySQL】(1) 数据库基础

一、什么是数据库 数据库自行选择了合适的数据结构来组织数据&#xff0c;方便用户写入&#xff08;存储介质&#xff0c;如硬盘&#xff0c;机器断电不会丢失数据&#xff09;和查询数据。在数据结构部分&#xff0c;我们讲到的 ArrayList、HashMap 集合类对象也能存储数据&am…

基于Spring Boot的产业园区智慧公寓管理系统设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

nginx+keepalived负载均衡及高可用

1 项目背景 keepalived除了能够管理LVS软件外&#xff0c;还可以作为其他服务的高可用解决方案软件。采用nginxkeepalived&#xff0c;它是一个高性能的服务器高可用或者热备解决方案&#xff0c;Keepalived主要来防止服务器单点故障的发生问题&#xff0c;可以通过其与Nginx的…

LeapVAD:通过认知感知和 Dual-Process 思维实现自动驾驶的飞跃

25年1月来自浙江大学、上海AI实验室、慕尼黑工大、同济大学和中科大的论文“LeapVAD: A Leap in Autonomous Driving via Cognitive Perception and Dual-Process Thinking”。 尽管自动驾驶技术取得长足进步&#xff0c;但由于推理能力有限&#xff0c;数据驱动方法仍然难以应…

STM32G431RBT6——(2)浅析Cortex-M4内核

本篇博客是一个对Cortex-M4内核了解性的简介&#xff0c;不会涉及到深奥的理论&#xff0c;请大家放心食用。 我们所学习的STM32G431RBT6单片机是基于ARM的Cotex-M4内核&#xff0c;因此我们有必要对此内核做一个大概了解。其实M4内核和M3内核有很大的相似之处&#xff0c;很多…

python-leetcode-删除并获得点数

740. 删除并获得点数 - 力扣&#xff08;LeetCode&#xff09; 解法 1&#xff1a;动态规划&#xff08;O(n) 时间&#xff0c;O(n) 空间&#xff09; class Solution:def deleteAndEarn(self, nums: List[int]) -> int:if not nums:return 0# 统计每个数的贡献points Cou…

【北京迅为】iTOP-RK3568OpenHarmony系统南向驱动开发-第4章 UART基础知识

瑞芯微RK3568芯片是一款定位中高端的通用型SOC&#xff0c;采用22nm制程工艺&#xff0c;搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码&#xff0c;支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU&#xff0c;可用于轻量级人工…

git 强推

1、查看git版本 git --version 如果你已经安装了 Git&#xff0c;可以检查是否安装成功&#xff1a; 打开命令提示符&#xff08;CMD&#xff09;或 PowerShell。输入 git --version&#xff0c;如果安装成功&#xff0c;应该会显示 Git 的版本信息。 2、强推 git push or…

server.servlet.session.timeout: 12h(HTTP 会话的超时时间为 12 小时)

从你提供的配置文件&#xff08;应该是 Spring Boot 的 application.yml 或 application.properties 文件&#xff09;来看&#xff0c;以下部分与会话超时时间相关&#xff1a; server:servlet:session:timeout: 12h # timeout: 30cookie:name: VENDER_SID会话超时时间的…

【论文笔记-ECCV 2024】AnyControl:使用文本到图像生成的多功能控件创建您的艺术作品

AnyControl&#xff1a;使用文本到图像生成的多功能控件创建您的艺术作品 图1 AnyControl的多控制图像合成。该研究的模型支持多个控制信号的自由组合&#xff0c;并生成与每个输入对齐的和谐结果。输入到模型中的输入控制信号以组合图像显示&#xff0c;以实现更好的可视化。 …

x64汇编下过程参数解析

简介 好久没上博客, 突然发现我的粉丝数变2700了, 真是这几个月涨的粉比我之前好几年的都多, 于是心血来潮来写一篇, 记录一下x64下的调用约定(这里的调用约定只针对windows平台) Windows下的x64程序的调用约定有别于x86下的"stdcall调用约定"以及"cdecl调用约…

WSDM24-因果推荐|因果去偏的可解释推荐系统

1 动机 可解释推荐系统&#xff08;ERS&#xff09;通过提供透明的推荐解释&#xff0c;提高用户信任度和系统的说服力&#xff0c;如下图所示&#xff0c;然而&#xff1a; 1&#xff1a;现有工作主要关注推荐算法的去偏&#xff08;流行度偏差&#xff09;&#xff0c;但未显…

深度解析 ANSI X9.31 TR-31:金融行业密钥管理核心标准20250228

深度解析 ANSI X9.31 TR-31&#xff1a;金融行业密钥管理核心标准 在当今数字化金融时代&#xff0c;信息安全至关重要&#xff0c;而密钥管理则是保障金融数据安全的核心环节。ANSI X9.31 TR-31作为金融行业密钥管理的关键标准&#xff0c;为对称密钥的全生命周期管理提供了坚…

Coredns延迟NodeLocalDNS解决之道

#作者&#xff1a;邓伟 文章目录 问题列表问题分析&#xff1a;问题分析解决方案详情方案验证部署步骤验证结论回滚方案回滚验证注意事项NodeLocalDNS介绍 问题列表 近来发现K8s频繁出现5s超时问题&#xff0c;业务反馈收到一定影响&#xff0c;问题包括&#xff1a; coredn…

Apollo Cyber 学习笔记

目录 0 Introduction What Why Advantage 1 Example 2 Concept 3 Flow Chart 4 Module 4.1 Transport 4.1.1 Share Memory 4.1.1.1 Segment 4.1.1.1.1 State 4.1.1.1.2 Block 4.1.1.1.3 Common 4.1.1.2 Notifier 4.1.1.2.1 ConditionNotifier 4.1.1.2.2 Multi…