【QT随笔】结合应用案例一文完美概括QT中的队列(Queue)

【QT随笔】结合应用案例一文完美概括QT中的队列(Queue)

队列(Queue)是一种线性数据结构,其核心规则为先进先出(FIFO, First-In-First-Out): 新元素在队尾插入(enqueue),旧元素从队头移除(dequeue);先到达的元素先被服务,次序严格保序。

(关注不迷路哈!!!)

文章目录

  • 【QT随笔】结合应用案例一文完美概括QT中的队列(Queue)
    • 前言
    • 一、使用 Qt 提供的容器类 QQueue 实现队列数据结构
      • 1. 元素操作
      • 2. 容量查询
      • 3. 访问元素
      • 4. 辅助功能
    • 二、使用事件队列 QEvent 与事件循环 QEventLoop 实现消息队列
      • 1. 事件循环 (QEventLoop) 工作机制
      • 2. QEvent 类层次结构
      • 3. 事件投递方式对比
      • 4. 自定义事件创建与处理
    • 三、多线程任务队列
    • 四、线程安全队列实现
    • 五、队列应用场景与实战案例
    • 六、队列性能优化与最佳实践
    • 七、不同类型队列对比汇总
    • 总结
      • 关键要点


前言

队列(Queue)是计算机科学中一种基础且重要的数据结构,它遵循先进先出(FIFO, First-In-First-Out)的原则。在Qt框架中,队列 不仅作为数据容器存在,更是事件处理、多线程编程和任务调度的核心机制。本文将全面探讨Qt中队列的实现方式、应用场景和最佳实践,帮助开发者更好地利用这一数据结构提升程序性能与可维护性。

一、使用 Qt 提供的容器类 QQueue 实现队列数据结构

📌 核心定位

QQueue 是Qt框架基于 QList 提供的模板容器类,专门用于实现队列数据结构。它提供了高效的入队(enqueue)和出队(dequeue)操作,适用于需要严格按顺序处理数据的场景。

🔑 核心功能

QQueue 提供了一系列直观易用的接口方法:

1. 元素操作

  • enqueue(const T &value):队尾添加元素
  • dequeue():移除并返回队首元素(调用时确保队列不为空)
  • head():返回队首元素(不移除)

2. 容量查询

  • isEmpty():检查队列是否为空
  • size():返回队列元素数量

3. 访问元素

  • first():返回队首元素
  • last():返回队尾元素
  • at(int index):返回指定位置元素

4. 辅助功能

  • clear():清空队列
  • contains(const T &value):检查是否包含某元素
  • count(const T &value):统计某元素出现次数
#include <QDebug>
#include <QQueue>int main()
{QQueue<int> queue; // 创建 Int 类型的队列对象// 入队操作queue.enqueue(10); // 入队元素queue.enqueue(20);queue.enqueue(30);// 查看队列状态qDebug() << "Queue size:" << queue.size();  // 输出: 3 // 获取队列大小qDebug() << "Queue head:" << queue.head();  // 输出: 10 // 查看队列的头部元素qDebug() << "Is empty:" << queue.isEmpty(); // 输出: false // 检查队列是否为空// 获取队列中的第一个和最后一个元素qDebug() << "第一个元素:" << queue.first();  // 输出: 第一个元素: 10qDebug() << "最后一个元素:" << queue.last(); // 输出: 最后一个元素: 30// 检查队列是否包含特定值,contains 继承自 `QList` 的函数qDebug() << "Queue contains 20:" << queue.contains(20); // 输出: Queue contains 20: true// 出队操作while (!queue.isEmpty()){int value = queue.dequeue(); // 出队元素qDebug() << "出队元素:" << value;}// 出队之后,检查队列是否包含特定值(20)qDebug() << "Queue contains 20:" << queue.contains(20); // 输出: Queue contains 20: falsequeue.clear();                                          // 清空队列,移除队列中的所有元素return 0;
}
Queue size: 3
Queue head: 10
Is empty: false
Queue contains 20: true
第一个元素: 10
最后一个元素: 30
出队元素: 10
出队元素: 20
出队元素: 30
Queue contains 20: false

QQueue的基本操作流程,包括创建队列、入队、出队以及循环处理直到队列为空的过程
在这里插入图片描述

二、使用事件队列 QEvent 与事件循环 QEventLoop 实现消息队列

📌 核心定位

Qt的​​事件队列​​和​​事件循环​​是框架运行的核心机制,这套机制不仅处理GUI应用程序的用户交互,更是所有异步操作跨线程通信的基石。通过 QEventLoop 对事件的分发和处理,Qt能够高效地处理用户输入、定时器事件和异步操作,确保应用程序既响应迅速又不会阻塞。

🔑 核心功能

1. 事件循环 (QEventLoop) 工作机制

事件循环是Qt应用程序的心脏,通常由QApplication::exec()启动。它是一个无限循环,持续检查并处理各种事件源。
事件循环基本工作原理

在这里插入图片描述

事件循环负责管理多个事件队列:

  • 系统事件队列:存放来自操作系统的原始消息(如鼠标点击、键盘输入)
  • QT事件队列 (Posted Events):通过QCoreApplication::postEvent()放入,异步执行
  • 发送事件队列 (Sent Events):通过QCoreApplication::sendEvent()放入,同步执行

事件还拥有不同的优先级(如Qt::HighEventPriorityQt::NormalEventPriorityQt::LowEventPriority),高优先级事件会"插队"处理。

2. QEvent 类层次结构

QEvent是所有事件的基类,Qt提供了丰富的事件子类用于不同场景:

事件类型用途典型应用场景
QMouseEvent鼠标操作点击、移动、拖拽
QKeyEvent键盘输入按键检测、快捷键
QPaintEvent绘图事件界面重绘
QTimerEvent定时器定时任务、动画
QCloseEvent关闭事件窗口关闭处理
QCustomEvent自定义事件应用程序特定逻辑

3. 事件投递方式对比

Qt提供了两种主要的事件投递方式:

特性postEvent()sendEvent()
执行方式异步同步
线程安全
内存管理Qt自动删除事件对象需要手动管理
适用场景跨线程通信、延迟处理立即处理、同一线程内

4. 自定义事件创建与处理

创建自定义事件需要以下步骤:

  • ① 定义自定义事件类型
  • ② 创建自定义事件类
  • ③ 投递自定义事件
  • ④ 处理自定义事件

事件队列的实现依赖于以下几个关键组件:

  • QEvent类:代表所有类型的事件
  • QCoreApplication::postEvent():将事件投递到事件队列
  • QEventLoop:管理事件循环的过程
  • QTimer:提供定时事件支持
#include <QApplication>
#include <QDebug>
#include <QTimer>// 创建自定义事件类
class CustomEvent : public QEvent
{
public:static const QEvent::Type Type = static_cast<QEvent::Type>(1000); // 定义自定义事件类型CustomEvent(const QString& message): QEvent(Type), m_message(message){}QString message() const { return m_message; }
private:QString m_message;
};// 事件接收器 // 处理自定义事件
class EventReceiver : public QObject
{
protected:bool event(QEvent* event) override{if (event->type() == CustomEvent::Type) {CustomEvent* customEvent = static_cast<CustomEvent*>(event);qDebug() << "Received event:" << customEvent->message();return true;}return QObject::event(event);}
};int main(int argc, char* argv[])
{QApplication app(argc, argv);EventReceiver receiver;// 投递自定义事件到事件队列 // // 异步投递 - 线程安全 // 注意:事件对象必须用new创建,Qt会自动删除QCoreApplication::postEvent(&receiver, new CustomEvent("Hello Event Queue!"));// 使用定时器触发事件QTimer::singleShot(1000, []() { qDebug() << "此处用于实现定时器事件处理"; }); // 1秒后触发return app.exec();
}
Received event: "Hello Event Queue!"
此处用于实现定时器事件处理

三、多线程任务队列

📌 核心定位

Qt提供了多种机制实现多线程任务队列,用于将耗时的操作转移到后台线程执行,保持UI线程的响应性。

🔑 核心功能

  1. QtConcurrent命名空间:提供高级API实现并行计算
  2. QThreadPool类:管理可重用的线程池
  3. QRunnable类:代表可执行的任务单元
#include <QtConcurrent>
#include <QThreadPool>
#include <QDebug>void processImage(const QString& imagePath) {// 模拟耗时图像处理qDebug() << "Processing image:" << imagePath << "in thread:" << QThread::currentThreadId();QThread::sleep(1);
}int main() {// 获取全局线程池QThreadPool* pool = QThreadPool::globalInstance();qDebug() << "Max threads:" << pool->maxThreadCount();QStringList imageList = {"image1.jpg", "image2.png", "image3.bmp", "image4.tiff"};// 使用QtConcurrent运行任务QtConcurrent::run(processImage, imageList[0]);// 使用QThreadPool执行任务class ImageTask : public QRunnable {public:ImageTask(const QString& path) : m_path(path) {}void run() override {processImage(m_path);}private:QString m_path;};for (int i = 1; i < imageList.size(); ++i) {pool->start(new ImageTask(imageList[i]));}// 等待所有任务完成pool->waitForDone();return 0;
}

四、线程安全队列实现

📌 核心定位

在多线程环境中,线程安全是队列实现的关键考虑因素。Qt提供了多种同步机制来确保多线程环境下数据访问的安全性。

🔑 核心功能

实现线程安全队列需要以下组件:

  • QMutex:提供互斥锁机制
  • QWaitCondition:允许线程在特定条件下等待
  • QMutexLocker:简化互斥锁的管理
#include <QQueue>
#include <QMutex>
#include <QWaitCondition>
#include <QSharedPointer>template<typename T>
class ThreadSafeQueue {
public:void enqueue(const T& value) {QMutexLocker locker(&m_mutex);m_queue.enqueue(value);m_condition.wakeOne();  // 唤醒一个等待线程}T dequeue() {QMutexLocker locker(&m_mutex);// 使用while而不是if来防止虚假唤醒while (m_queue.isEmpty()) {m_condition.wait(&m_mutex);}return m_queue.dequeue();}bool isEmpty() const {QMutexLocker locker(&m_mutex);return m_queue.isEmpty();}int size() const {QMutexLocker locker(&m_mutex);return m_queue.size();}private:mutable QMutex m_mutex;QWaitCondition m_condition;QQueue<T> m_queue;
};// 使用示例:图像处理管道
class ImageProcessor : public QObject {Q_OBJECT
public:void addImage(const QImage& image) {m_queue.enqueue(image);}void startProcessing() {QThread* thread = QThread::create([this]() {while (!m_stopRequested) {QImage image = m_queue.dequeue();// 处理图像processImage(image);QThread::msleep(50);}});thread->start();}void stopProcessing() {m_stopRequested = true;}private:ThreadSafeQueue<QImage> m_queue;bool m_stopRequested = false;
};

五、队列应用场景与实战案例

📌 核心定位

队列在Qt开发中有多种实际应用场景,从简单的数据缓冲到复杂的系统架构。

🔑 核心功能

  1. 任务调度系统:使用队列管理待处理任务
  2. 数据缓冲:处理生产者-消费者速度不匹配问题
  3. 事件处理:管理GUI事件和异步操作
  4. 算法实现:广度优先搜索等算法的基础

实战案例:图像批处理系统

#include <QQueue>
#include <QImage>
#include <QDir>
#include <QDebug>class ImageBatchProcessor : public QObject {Q_OBJECT
public:void loadImagesFromDirectory(const QString& directoryPath) {QDir directory(directoryPath);QStringList filters{"*.png", "*.jpg", "*.bmp"};QStringList imageFiles = directory.entryList(filters, QDir::Files);for (const QString& filename : imageFiles) {QString fullPath = directory.filePath(filename);QImage image(fullPath);if (!image.isNull()) {m_imageQueue.enqueue(image);qDebug() << "Loaded image:" << fullPath;}}emit imagesLoaded(m_imageQueue.size());}void processImages() {while (!m_imageQueue.isEmpty()) {QImage image = m_imageQueue.dequeue();QTime startTime = QTime::currentTime();// 执行图像处理操作QImage processedImage = processSingleImage(image);int processingTime = startTime.msecsTo(QTime::currentTime());qDebug() << "Image processed in" << processingTime << "ms";emit imageProcessed(processedImage);}emit processingFinished();}signals:void imagesLoaded(int count);void imageProcessed(const QImage& image);void processingFinished();private:QQueue<QImage> m_imageQueue;QImage processSingleImage(const QImage& image) {// 这里实现具体的图像处理算法// 例如: 垂直翻转图像return image.mirrored(false, true);}
};

六、队列性能优化与最佳实践

📌 核心定位

合理使用和优化队列对提升应用程序性能至关重要

🔑 核心功能

  1. 内存预分配:对于可预测大小的队列,提前分配内存
  2. 移动语义:使用C++11移动语义减少拷贝开销
  3. 批量处理:减少锁竞争和提高缓存效率
  4. 队列大小监控:防止内存无限增长
#include <QQueue>
#include <QVector>template<typename T>
class OptimizedQueue {
public:OptimizedQueue(int initialCapacity = 1000) {m_queue.reserve(initialCapacity);}void enqueue(const T& value) {QMutexLocker locker(&m_mutex);m_queue.enqueue(value);}void enqueue(T&& value) {QMutexLocker locker(&m_mutex);m_queue.enqueue(std::move(value));  // 使用移动语义}// 批量入队,减少锁竞争void enqueueBatch(const QVector<T>& values) {QMutexLocker locker(&m_mutex);for (const T& value : values) {m_queue.enqueue(value);}m_condition.wakeAll();  // 唤醒所有等待线程}// 批量出队,提高处理效率QVector<T> dequeueBatch(int maxSize = 10) {QMutexLocker locker(&m_mutex);QVector<T> result;result.reserve(maxSize);while (!m_queue.isEmpty() && result.size() < maxSize) {result.append(m_queue.dequeue());}return result;}// 监控队列大小,防止内存溢出bool isAboveThreshold(int threshold = 10000) const {QMutexLocker locker(&m_mutex);return m_queue.size() > threshold;}private:mutable QMutex m_mutex;QWaitCondition m_condition;QQueue<T> m_queue;
};

七、不同类型队列对比汇总

📌 核心定位

Qt提供了多种队列实现方式,每种方式适用于不同的应用场景

🔑 核心功能

以下是Qt中主要队列类型的对比表:

队列类型特点适用场景性能特点
QQueue基于QList,简单易用单线程环境,数据管理O(1)入队出队操作
事件队列集成于事件循环,自动管理GUI应用,异步处理事件驱动,高效响应
QtConcurrent高级API,自动线程管理并行计算,CPU密集型任务多核优化,负载均衡
自定义线程安全队列完全控制,可高度定制多线程数据交换,复杂同步需求依赖实现方式,可优化

选择指南

  • 简单数据存储:使用QQueue
  • GUI事件处理:依赖内置事件队列
  • 并行计算:选择QtConcurrent
  • 复杂多线程同步:实现自定义线程安全队列

总结

队列是Qt框架中多功能且强大的工具,贯穿于数据管理、事件处理和多线程编程等多个核心领域。通过合理选择和使用适当的队列类型,开发者可以构建出高效、响应迅速且可靠的应用程序。

关键要点

  1. 选择合适的队列类型:根据具体需求选择最合适的队列实现
  2. 重视线程安全:在多线程环境中务必使用适当的同步机制
  3. 性能考虑:对于高性能场景,优化队列实现和内存使用
  4. 集成Qt生态系统:充分利用Qt提供的各种队列相关工具和框架

Qt队列机制的有效运用不仅能提升程序性能,还能增强代码的可维护性和可扩展性,是每个Qt开发者应该掌握的核心技能。

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

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

相关文章

At least one <template> or <script> is required in a single file component

环境rspack vue3原因rule 中配置了两个vue-loader删掉一个即可。

LangChain实战(十八):构建ReAct模式的网页内容摘要与分析Agent

本文是《LangChain实战课》系列的第十八篇,将深入讲解如何构建一个基于ReAct模式的智能网页内容摘要与分析Agent。这个Agent能够自主浏览网页、提取关键信息、生成智能摘要,并进行深入的内容分析,让信息获取和理解变得更加高效。 前言 在信息爆炸的时代,我们每天都需要处理…

debian11 ubuntu24 armbian24 apt install pure-ftpd被动模式的正确配置方法

debian11 ubuntu24 armbian24 apt install pure-ftpd被动模式的正确配置方法 安装方法请看&#xff1a;https://www.itbulu.com/pure-ftpd.html 疑难问题解决 原本以为配置很简单的&#xff0c;无非是修改 ForcePassiveIP MinUID PassivePortRange PureDB这几个配置项就行了…

量化金融|基于算法和模型的预测研究综述

一、研究背景与发展历程​​1.​​量化投资理论演进​​•奠基阶段&#xff08;1950s-1960s&#xff09;​​&#xff1a;Markowitz均值方差理论&#xff08;1952&#xff09;、CAPM模型&#xff08;1964&#xff09;奠定现代量化投资基础•衍生品定价&#xff08;1970s-1980s&…

从零开始的云计算生活——第六十天,志在千里,使用Jenkins部署K8S

一.安装kubectl1、配置yum源cat <<EOF | tee /etc/yum.repos.d/kubernetes.repo [kubernetes] nameKubernetes baseurlhttps://mirrors.aliyun.com/kubernetes-new/core/stable/v1.28/rpm/ enabled1 gpgcheck1 gpgkeyhttps://mirrors.aliyun.com/kubernetes-new/core/sta…

无人机电压模块技术剖析

无人机电源模块的基本运行方式无人机电压模块的核心任务是对动力电源&#xff08;通常是锂电池&#xff09;进行转换、调节和分配&#xff0c;为飞控、图传、摄像头、舵机等各个子系统提供稳定可靠的电能。其运行方式可以概括为&#xff1a;电压转换与调控&#xff1a;无人机动…

MATLAB基于GM(灰色模型)与LSTM(长短期记忆网络)的组合预测方法

一、GM与LSTM的基本原理及互补性 1. GM模型的核心特点基本原理&#xff1a;通过累加生成&#xff08;AGO&#xff09;将原始无序序列转化为具有指数规律的光滑序列&#xff0c;建立一阶微分方程&#xff08;如GM(1,1)&#xff09;进行预测。其数学形式为&#xff1a; dx(1)dtax…

【菜狗每日记录】启发式算法、傅里叶变换、AC-DTC、Xmeans—20250909

&#x1f431;1、启发式算法 ① 定义 ② 特点 ③ 案例 &#x1f431;2、快速傅里叶变换FFT ① DFT离散傅里叶变换 ② FFT快速傅里叶变换 &#x1f431;3、AC-DTC聚类 &#x1f431;4、Xmeans &#x1f431;1、启发式算法 启发式算法是和最优化算法相对的。 一般而言&am…

Axure移动端选择器案例:多类型选择器设计与动态效果实现

在移动端交互设计中&#xff0c;选择器是用户输入的核心组件。Axure移动端高保真元件库提供了四种关键选择器解决方案&#xff0c;通过动态效果提升操作真实感&#xff1a; 预览地址&#xff1a;Axure 1. 基础选择器 采用底部弹窗设计&#xff0c;支持单选项快速选择。点击触发…

Spring Boot图片验证码功能实现详解 - 从零开始到完美运行

Spring Boot图片验证码功能实现详解 - 从零开始到完美运行 &#x1f4d6; 前言 大家好&#xff01;今天我要和大家分享一个非常实用的功能&#xff1a;Spring Boot图片验证码。这个功能可以防止恶意攻击&#xff0c;比如暴力破解、刷票等。我们实现的是一个带有加减法运算的图片…

HarmonyOS实现快递APP自动识别地址

​ 大家好&#xff0c;我是潘Sir&#xff0c;持续分享IT技术&#xff0c;帮你少走弯路。《鸿蒙应用开发从入门到项目实战》系列文章持续更新中&#xff0c;欢迎关注&#xff01; 随着鸿蒙&#xff08;HarmonyOS&#xff09;生态发展&#xff0c;越来越多的APP需要进行鸿蒙适…

CUDA编程13 - 测量每个Block的执行时间

一:概述 GPU 程序性能不是靠 CPU 那样的“顺序执行”来衡量的,而是靠线程块(block)和多处理器(SM)利用率。每个 block 在 GPU 的不同多处理器上执行,顺序不确定。传统的 kernel 总体计时(比如 cudaEvent 计时整个 kernel)只能知道总时间,无法分析哪个 block 慢,为什…

敏捷开发-Scrum(下)

Scrum 核心构成&#xff1a;团队、事件与工件的协同价值体系 在 Scrum 框架中&#xff0c;“团队、事件、工件” 并非孤立的模块&#xff0c;而是相互咬合的有机整体&#xff1a;Scrum 团队是价值交付的执行核心&#xff0c;Scrum 事件是节奏把控与反馈调整的机制载体&#xff…

LeetCode 单调栈 739. 每日温度

739. 每日温度给定一个整数数组 temperatures &#xff0c;表示每天的温度&#xff0c;返回一个数组 answer &#xff0c;其中 answer[i] 是指对于第 i 天&#xff0c;下一个更高温度出现在几天后。如果气温在这之后都不会升高&#xff0c;请在该位置用 0 来代替。 示例 1: 输入…

Java-面试八股文-JVM篇

JVM篇 一.在JVM中&#xff0c;什么是程序计数器? 在 JVM&#xff08;Java Virtual Machine&#xff09; 中&#xff0c;程序计数器&#xff08;Program Counter Register&#xff0c;简称 PC 寄存器&#xff09; 是一块较小的内存空间&#xff0c;用于记录 当前线程所执行的字…

微算法科技(NASDAQ: MLGO)采用量子相位估计(QPE)方法,增强量子神经网络训练

随着量子计算技术的迅猛发展&#xff0c;传统计算机在处理复杂问题时所遇到的算力瓶颈日益凸显。量子计算以其独特的并行计算能力和指数级增长的计算潜力&#xff0c;为解决这些问题提供了新的途径。微算法科技&#xff08;NASDAQ: MLGO&#xff09;探索量子技术在各种应用场景…

MySQL 备份的方法和最佳实践

MySQL 是一种流行的开源关系数据库管理系统&#xff0c;用于在线应用程序和数据仓库。它以可靠性、有效性和简单性而闻名。然而&#xff0c;与任何计算机系统一样&#xff0c;由于硬件故障、软件缺陷或其他不可预见的情况&#xff0c;存在数据丢失的可能性。因此&#xff0c;保…

应用层自定义协议、序列化和反序列化

1.自定义协议开发者根据特定应用场景的需要&#xff0c;自行设计和制定的通信规则和数据格式 1.1 核心组成部分一个典型的自定义协议通常包含以下几个关键部分&#xff1a;​帧/报文格式 (Frame/Packet Format)​​&#xff1a;定义了数据是如何打包的。这通常包括&#xff1a…

Excel VBA 中可用的工作表函数

Visual Basic for Applications (VBA) 中可用的工作表函数。可以在 VBA 中通过 Application.WorksheetFunction 对象调用。 下面我将按照字母分组&#xff0c;对每个函数进行简要解释&#xff0c;并给出在 VBA 中使用的示例。A 组Acos: 返回数字的反余弦值。 result Applicati…

OpenWrt + Docker 完整部署方案:CFnat + Cloudflared 一体化集成

AI生成&#xff08;可能是AI幻觉&#xff09; 项目架构概述 基于您现有的网络配置&#xff08;IP: 192.168.1.1&#xff09;&#xff0c;本方案将CFnat服务作为网络优化层整合到现有的Cloudflare隧道架构中&#xff0c;实现完整的网络加速解决方案。 优化后的流量路径 用户访问…