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程序后台任务:**保持界面响应性,耗时操作放入任务队列。
通过这种模式,可以轻松实现高并发任务处理,同时避免手动管理线程的复杂性。
相关文章:
Qt基于等待条件QWaitCondition实现的任务队列模型示例
核心概念 Qt中的QWaitCondition是一个用于多线程同步的类,允许线程在某些条件满足时唤醒其他等待的线程。它通常与QMutex配合使用,协调线程之间的执行顺序,适用于生产者-消费者模型、任务队列调度等场景。 wait():使当前线程进…...

微服务即时通信系统---(六)语音识别子服务
目录 功能设计 模块划分 业务接口/功能示意图 服务实现流程思想 服务代码实现 编写proto文件 服务端创建子类(SpeechRecognitionServiceImpl)完成RPC服务调用函数重写 SpeechRecognize(语音识别) 服务端完成语音识别子服务类(SpeechRecognitionServer) 注意 …...

JavaWeb基础专项复习5——请求对象和响应对象request and response
系列文章目录 1、JavaWeb基础专项复习1——XML文件-CSDN博客 2、JavaWeb基础专项复习2——JSP文件-CSDN博客 3、JavaWeb基础专项复习2——Servlet相关知识-CSDN博客 4、JavaWeb基础专项复习4——会话对象Session and Cookie-CSDN博客 文章目录 系列文章目录文章目录1、Tom…...

mac下载MAMP6.8.1;解决mac使用小皮面板安装php7.4
因为mac的小皮面板没有php7.4了 链接:c9cc270e6961c17c.dmg官方版下载丨最新版下载丨绿色版下载丨APP下载-123云盘 鹅选一 附上大佬写的教程:MAMP PRO教程 - 牛奔 - 博客园 更新一下,2-27 昨天已经可以使用php7.4了,我就在想能…...

大模型WebUI:Gradio全解12——LangChain原理、架构和组件(3)
大模型WebUI:Gradio全解12——LangChain原理、架构和组件(3) 前言本篇摘要12. LangChain原理及agents构建Gradio UI12.3 LangChain架构12.3.1 LangChain12.3.2 Integration Packages1. 概念2. 示例12.3.3 LangGraph1. 概念2. 示例12.3.4 LangGraph Platform1. 概览2. 优势分…...

redis --- 相关基础知识整理
目录 一、基本1、数据结构2、有序集合的编码1. 压缩列表(Ziplist)2. 跳跃列表(SkipList)3. 动态转换机制 二、应用场景三、持久化1、 RDB 持久化2、 AOF 持久化3、 混合持久化(RDB AOF)4、 RDB和AOF的对比…...
如何用 Python 进行机器学习
文章目录 前言1. 环境准备Python安装选择Python开发环境安装必要库 2. 数据收集与加载3. 数据探索与可视化4. 数据预处理5. 模型选择与训练6. 模型评估7. 模型调优8. 模型部署 前言 使用 Python 进行机器学习一般可以按照以下步骤进行,下面将详细介绍每个步骤及对应…...

《Effective Objective-C》阅读笔记(下)
目录 内存管理 理解引用计数 引用计数工作原理 自动释放池 保留环 以ARC简化引用计数 使用ARC时必须遵循的方法命名规则 变量的内存管理语义 ARC如何清理实例变量 在dealloc方法中只释放引用并解除监听 编写“异常安全代码”时留意内存管理问题 以弱引用避免保留环 …...
解释Promise的工作原理及其状态
Promise的工作原理及其状态 1. 什么是Promise? Promise是JavaScript中的一种用于处理异步操作的对象。它代表一个可能在未来某个时间点完成的操作,并且可以有三种状态:待定(pending)、已解决(fulfilled&a…...
SHELL32!ILCombine函数分析之连接两个idl
SHELL32!ILCombine函数分析之连接两个idl 第一部分: STDAPI_(LPITEMIDLIST) ILCombine(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2) { // Let me pass in NULL pointers if (!pidl1) { if (!pidl2) { return NULL; …...
es 生产集群的部署架构是什么?每个索引的数据量大概有多少?每个索引大概有多少个分片?
Elasticsearch 生产集群部署架构及面试解析 在后端面试中,Elasticsearch(ES)是一个经常被问到的技术点,尤其是涉及到 生产环境的部署架构。面试官往往希望通过这个问题来验证你是否有真正的生产经验,而不仅仅是玩过一…...
Qt跨线程信号槽调用:为什么信号不能像普通函数那样调用
1. 信号与槽机制的基本原理 在 Qt 中,信号与槽机制是一种事件驱动的通信方式,用于对象之间的解耦交互。其关键特点如下: 信号不能直接调用 信号只是一个声明,并没有实际的函数实现。它们通过 emit 关键字在对象内部被触发&…...

ollama和open-webui部署ds
博客地址: ollama和open-webui部署ds 引言 最近,deepseek是越来越火,我也趁着这个机会做了下私有化部署,我这边使用的ollama和 open-webui实现的web版本 ollama 简介 Ollama 是一个开源的工具,专门用于简化机器学…...
泛微Ecode新增Button调用服务器中的JSP页面里的方法
前言 前端Ecode调用 后端接口编写 JSP文件方法 总结 前言 因为我们是从之前E8版本升级到E9的,所以会有一些接口是通过jsp文件来实现前后端调用的,这里介绍的就是如果你有接口是写在jsp文件里面调用的,但是你又想在Ecode中调用的对应的接…...
LVS+Keepalived高可用群集配置案例
以下是一个 LVSKeepalived 高可用群集配置案例: 1、环境准备 LVS 主调度器(lvs1):IP 地址为 192.168.8.101,心跳 IP 为 192.168.4.101LVS 备调度器(lvs2):IP 地址为 192.168.8.102…...

杰发科技AC7801——滴答定时器获取时间戳
1. 滴答定时器 杰发科技7801内部有一个滴答定时器,该定时器是M0核自带的,因此可以直接用该定时器来获取时间戳。 同样,7803也可以使用该方式获取时间戳。 2. 滴答定时器原理 SysTick是一个24位的递减计数器,它从预设的重装载值…...

Pycharm使用matplotlib出现的问题(1、不能弹出图表 2、图表标题中文不显示)
Pycharm使用matplotlib出现的问题 问题1:Pycharm调试时出现:AttributeError: module backend_interagg has no attribute FigureCanvas. Did you mean: FigureCanvasAgg? 排查原因:可能是由于matplotlib后端设置不正确或与运行环境不兼容引…...

Cursor+pycharm接入Codeuim(免费版),Tab自动补全功能平替
如题,笔者在Cursor中使用pycharm写python程序,试用期到了Tab自动补全功能就不能用了,安装Codeuim插件可以代替这个功能。步骤如下: 1. 在应用商店中搜索扩展Codeuim,下载安装 2. 安装完成后左下角会弹出提示框&#x…...
spring--ApplicationContext和BeanFactory的区别(源码)
ApplicationContext 和 BeanFactory 是 Spring 框架中两个核心的接口,它们都用于管理和访问 Spring 容器中的 Bean,但在功能和使用场景上有显著的区别。以下是它们的详细对比,并结合源码进行讲解。 一、 功能对比 特性BeanFactoryApplicati…...

HTMLS基本结构及标签
HTML5是目前制作网页的核心技术,有叫超文本标记语言。 基本结构 声明部分位于文档的最前面,用于向浏览器说明当前文档使用HTML标准规范。 根部标签位于声明部分后,用于告知浏览器这是一个HTML文档。< html>表示文档开始,&l…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...

Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...

大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...

如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...