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…...
OpenClaw开源贡献:为Qwen3.5-9B编写自定义技能指南
OpenClaw开源贡献:为Qwen3.5-9B编写自定义技能指南 1. 为什么要为OpenClaw开发自定义技能 去年冬天,当我第一次尝试用OpenClaw自动整理电脑上堆积如山的会议录音时,发现现有的技能库无法满足我的个性化需求。这促使我深入研究如何为这个开源…...
2026全球AI产业发展全景:模型竞争、多模态应用与生态格局深度解析
2026年,人工智能产业进入技术落地与生态扩张并行的深化阶段,从基础模型迭代到行业场景渗透,均呈现出高度成熟的发展态势。对于个人用户与企业开发者而言,高效整合全球AI能力已成为提升效率的关键。https://n.kulaai.cn 作为一站式AI模型与工具聚合平台,汇集了ChatGPT、Cla…...
qmc-decoder:QMC加密音乐格式转换工具的全方位应用指南
qmc-decoder:QMC加密音乐格式转换工具的全方位应用指南 【免费下载链接】qmc-decoder Fastest & best convert qmc 2 mp3 | flac tools 项目地址: https://gitcode.com/gh_mirrors/qm/qmc-decoder 一、问题引入:当音乐文件被"锁住"…...
RWKV7-1.5B-G1A模型部署与MATLAB科学计算联动方案
RWKV7-1.5B-G1A模型部署与MATLAB科学计算联动方案 1. 引言:科研工作者的新助手 科研工作中最耗时的往往不是实验本身,而是数据处理后的文字工作。想象这样一个场景:你刚完成一组复杂的MATLAB仿真实验,面对密密麻麻的数据图表&am…...
Cadence 17.4 保姆级教程:从Database Check到Gerber文件一键导出(附嘉立创预览指南)
Cadence 17.4 全流程制板文件导出实战指南:从设计验证到生产交付 在PCB设计领域,Cadence Allegro作为行业标准工具链的核心组成部分,其制板文件导出流程的规范性直接关系到生产质量与成本控制。本文将系统梳理从设计完成到Gerber文件交付的完…...
程序员必看!高质量免费源码网推荐
在数字化浪潮席卷全球的今天,代码已成为驱动创新的核心动力。无论是初创企业快速搭建商业平台,还是开发者优化项目架构,高质量的源码资源都能显著缩短研发周期、降低开发成本。然而,面对网络上鱼龙混杂的源码平台,如何…...
DeepSeek-R1蒸馏模型入门:1.5B版本本地部署完整教程
DeepSeek-R1蒸馏模型入门:1.5B版本本地部署完整教程 1. 引言 1.1 为什么选择DeepSeek-R1 1.5B版本 DeepSeek-R1 1.5B版本是专为本地CPU环境优化的轻量级推理模型,它通过知识蒸馏技术保留了原版70B参数模型的核心推理能力,同时将参数量压缩…...
《思想合奏:一场关于“自感即界面即自我”的深度对话综述》
《思想合奏:一场关于“自感即界面即自我”的深度对话综述》目录引言:从文本到事件一、起点:核心概念的厘定二、深化:五重维度的展开三、突破:自感诚实度循环与痕迹可检测性四、建构:伦理中间件与抵抗策略五…...
SEO优化软件年费用大概是多少
SEO优化软件年费用大概是多少 SEO优化软件已经成为许多企业和网站运营者必不可少的工具。它能够帮助提升网站在搜索引擎中的排名,从而带来更多的流量和潜在客户。但在选择和使用SEO优化软件时,很多人都会关心一个问题:SEO优化软件年费用大概…...
zRenamer 1.9 批量重命名工具
一、软件背景 1. 核心痛点来源 日常文件管理中,用户长期面临批量重命名低效、混乱、易出错的核心痛点: 手动操作繁琐:零散文件(照片、文档、视频)命名无规则,手动修改数百个文件耗时极长,重复…...
