Qt 中的队列解析

张开发
2026/4/20 20:46:18 15 分钟阅读

分享文章

Qt 中的队列解析
Qt 中的队列解析一、Qt 中的队列解析二、代码示例一、Qt 中的队列解析Qt 提供了多种机制来实现类似队列的功能主要涉及以下几个方面数据结构队列QQueueT本质QQueueT是一个模板类它实际上是QListT的一个便捷别名。它提供了先进先出FIFO的队列操作接口。核心操作enqueue(const T value): 将元素value添加到队列的尾部入队。T dequeue(): 移除并返回队列头部的元素出队。如果队列为空行为未定义通常会导致崩溃使用前最好检查isEmpty()。T head(): 返回队列头部元素的引用不移除。const T head() const: 返回队列头部元素的常量引用不移除。T first(): 同head()。const T first() const: 同head() const。T last(): 返回队列尾部元素的引用。const T last() const: 返回队列尾部元素的常量引用。bool isEmpty() const: 检查队列是否为空。int size() const: 返回队列中元素的数量。示例#includeQQueue#includeQDebugintmain(){QQueueintqueue;// 入队queue.enqueue(10);queue.enqueue(20);queue.enqueue(30);// 检查头部qDebug()Head:queue.head();// 输出 10// 出队intfirstOutqueue.dequeue();// firstOut 10qDebug()Dequeued:firstOut;// 再次检查头部qDebug()Head now:queue.head();// 输出 20return0;}注意QQueue本身不是线程安全的。如果需要在多线程环境中使用队列必须使用互斥锁如QMutex或QReadWriteLock进行保护。跨线程通信队列信号与槽的队列连接 (Qt::QueuedConnection)概念这是 Qt 事件驱动和线程模型的核心机制之一。当信号通过队列连接 (Qt::QueuedConnection) 方式连接到槽时信号的发射并不会立即调用槽函数。工作原理信号发射时一个包含信号参数副本的事件QMetaCallEvent被放入接收者对象所在线程的事件队列中。接收者线程的事件循环 (QEventLoop) 在后续的某个时刻当它处理事件队列时会取出这个事件。事件循环根据事件中的信息调用对应的槽函数。特点异步执行槽函数在接收者线程中异步执行与信号发射线程解耦。这保证了线程安全。跨线程通信这是不同线程间对象通信的标准和安全方式。事件驱动依赖于接收者线程正在运行的事件循环。连接方式QObject::connect(sender,Sender::signalName,receiver,Receiver::slotName,Qt::QueuedConnection);// 显式指定队列连接当sender和receiver位于不同线程且没有显式指定连接类型时默认的连接类型Qt::AutoConnection会被解释为Qt::QueuedConnection。示例场景工作线程完成计算后通过信号将结果发送到主线程的某个对象进行处理如更新 UI。任务队列QThreadPool和QRunnable概念QThreadPool管理了一个线程池用于执行可运行的任务 (QRunnable)。你可以将多个QRunnable对象提交给线程池它们会被放入一个内部队列中。工作原理用户创建继承自QRunnable的子类并重写run()方法定义任务逻辑。创建该任务对象。调用QThreadPool::globalInstance()-start(runnable)将任务提交给全局线程池。线程池中的空闲线程会从队列中取出任务并执行其run()方法。如果所有线程都忙新提交的任务会排队等待直到有线程空闲。特点任务队列线程池内部维护了一个待执行任务的队列。线程复用避免了频繁创建和销毁线程的开销。并行执行允许多个任务在多个线程上并行执行取决于线程池大小。管理可以设置全局线程池或创建私有线程池并设置最大线程数等。示例#includeQRunnable#includeQThreadPool#includeQDebugclassMyTask:publicQRunnable{public:voidrun()override{qDebug()Task running in thread:QThread::currentThread();// 执行耗时操作...}};intmain(){MyTask*task1newMyTask();MyTask*task2newMyTask();// 提交任务到全局线程池队列QThreadPool::globalInstance()-start(task1);QThreadPool::globalInstance()-start(task2);// 主线程可以继续执行其他操作...return0;}总结Qt 中的“队列”概念体现在几个层面QQueueT作为数据结构提供 FIFO 操作。适用于单线程或受保护的多线程环境。信号与槽的Qt::QueuedConnection作为跨线程通信机制的核心。信号发射被转换为事件放入接收线程的事件队列由事件循环异步处理。这是实现线程间安全通信的标准方式。QThreadPool管理一个任务队列。用户提交的QRunnable任务被排队由线程池中的工作线程取出执行实现任务的并行处理。二、代码示例#includeQCoreApplication#includeQQueue#includeQMutex#includeQMutexLocker#includeQThread#includeQDebug// 全局队列 互斥锁多线程必须加锁QQueueintg_queue;QMutex g_mutex;// 生产者线程往队列里放数据classProducer:publicQThread{protected:voidrun()override{for(inti1;i10;i){// 自动加锁/解锁QMutexLockerlocker(g_mutex);g_queue.enqueue(i);qDebug()生产i 队列大小g_queue.size();// 模拟耗时msleep(200);}}};// 消费者线程从队列取数据classConsumer:publicQThread{protected:voidrun()override{while(true){QMutexLockerlocker(g_mutex);if(!g_queue.isEmpty()){intvalg_queue.dequeue();qDebug()消费val 队列大小g_queue.size();}else{// 队列为空稍等再取qDebug()队列为空等待...;}msleep(300);}}};intmain(intargc,char*argv[]){QCoreApplicationa(argc,argv);Producer p;Consumer c;p.start();c.start();p.wait();c.wait();returna.exec();}运行结果08:57:14:Starting G:\Learning\Qt\QJsonSchema\build\Desktop_Qt_6_9_0_MinGW_64_bit-Debug\debug\QJsonSchema.exe...生产1队列大小1生产2队列大小2生产3队列大小3生产4队列大小4生产5队列大小5生产6队列大小6生产7队列大小7生产8队列大小8生产9队列大小9生产10队列大小10消费1队列大小9消费2队列大小8消费3队列大小7消费4队列大小6消费5队列大小5消费6队列大小4消费7队列大小3消费8队列大小2消费9队列大小1消费10队列大小0队列为空等待...队列为空等待...队列为空等待...队列为空等待...队列为空等待...队列为空等待...队列为空等待...队列为空等待...队列为空等待...队列为空等待...队列为空等待...队列为空等待...队列为空等待...队列为空等待...队列为空等待...

更多文章