Qt-多线程-QThread分析总结

2024-06-11 20:18

本文主要是介绍Qt-多线程-QThread分析总结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

QThread是Qt提供的线程类,每一个QThread均可管理一个线程。

其具有两种使用方式:1、继承为QThread的子类;2、继承为QObject的子类,并使用QObject::moveToThread将此对象移到线程中运行

QThread提供了如下基本函数:

线程启动:start()运行一次

线程终止:terminate 终止线程,强制终止线程但会依据操作系统的调度策略,可能不是立即终止,最好用wait等待
quit退出线程,也可以调用exit,效果相同,会正常终止线程。

线程状态查询:isRunning是否正在运行,isFinished是否运行完成

线程状态信号:started线程启动时发出,finished线程结束时发出

其他:wait阻塞方式等待线程结束,调用此函数会将调用指令所在函数阻塞

建议对finished信号建立对应槽,实现线程结束后操作,而不是使用wait等待

更多详细说明见官方文档

线程优先级

start函数有一个参数是线程优先级,此处使用的默认参数,若未设置也可以调用setPriority函数设置优先级,优先级分为以下几类:

ConstantValueDescription
QThread::IdlePriority0scheduled only when no other threads are running.
QThread::LowestPriority1scheduled less often than LowPriority.
QThread::LowPriority2scheduled less often than NormalPriority.
QThread::NormalPriority3the default priority of the operating system.
QThread::HighPriority4scheduled more often than NormalPriority.
QThread::HighestPriority5scheduled more often than HighPriority.
QThread::TimeCriticalPriority6scheduled as often as possible.
QThread::InheritPriority7use the same priority as the creating thread. This is the default.

线程休眠

sleep秒休眠、msleep毫秒休眠、usleep微秒休眠

基本使用

建立QThread子类法

//mythread.h
#pragma once
#include <QThread>
#include <QDebug>
class MyThread : public QThread {Q_OBJECT
protected:void run() {while(1) {num++;qDebug()<<num<<"thread start:"<<QThread::currentThreadId();msleep(500);qDebug()<<num<<"thread end:"<<QThread::currentThreadId();}}
private:int num = 0;
};
//main.cpp
#include <QCoreApplication>
#include <QThread>
#include <QDebug>
#include "mythread.h"
int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);qDebug()<<"Main:"<<QThread::currentThreadId();MyThread m;m.start();QThread::sleep(5);m.terminate();m.wait();return 0;
}

上述代码测试了线程启动、强制停止以及currentthreadid获取当前线程id。

还可以使用currentthread获取当前线程指针函数

上述使用terminate强制关闭线程,此行为不建议使用,安全结束方式请见QThread安全的结束线程-Coologic

moveToThread方法

#pragma once
#include <QThread>
#include <QDebug>
class MyThread : public QObject {Q_OBJECT
public slots://注意要用槽函数void start() {qDebug()<<"thread end:"<<QThread::currentThreadId();}
};
#include <QCoreApplication>
#include <QThread>
#include <QDebug>
#include "mythread.h"
int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);qDebug()<<"Main:"<<QThread::currentThreadId();QThread thread;MyThread m;m.moveToThread(&thread);QObject::connect(&thread,SIGNAL(started()),&m,SLOT(start()));thread.start();return 0;
}

线程同步

QMutex互斥量

帮助文档

通过lock,unlock实现加锁、解锁

使用tryLock尝试加锁,会返回加锁成功与否,同时可设置超时时间。

注意在lock以后,任意return前必须进行unlock,否则会造成死锁

QMutexLocker

建立一个QMutex,通过QMutexLocker locker(&mutex);可以实现对mutex的自动处理,后续不需要自行进行lock和unlock,避免多个return情况下出现遗忘。

帮助文档范例:

只是用QMutex的代码:

int complexFunction(int flag) {mutex.lock();int retVal = 0;switch (flag) {case 0:case 1:retVal = moreComplexFunction(flag);break;case 2:  {int status = anotherFunction();if (status < 0) {mutex.unlock();return -2;}retVal = status + flag;}break;default:if (flag > 10) {mutex.unlock();return -1;}break;}mutex.unlock();return retVal;
}

使用QMutexLocker 代码

int complexFunction(int flag) {QMutexLocker locker(&mutex);int retVal = 0;switch (flag) {case 0:case 1:return moreComplexFunction(flag);case 2: {int status = anotherFunction();if (status < 0)return -2;retVal = status + flag;}break;default:if (flag > 10)return -1;break;}return retVal;
}

QReadWriteLock

使用QMutex无论对变量进行何种操作(读写)均会锁定变量,而实际上对于读取变量值并不需要等待,可以多个线程同时读取,此时使用QReadWriteLock可以实现多线程读,单线程写的操作。帮助文档

范例:

QReadWriteLock lock;
void ReaderThread::run() {...lock.lockForRead();read_file();lock.unlock();...
}void WriterThread::run() {...lock.lockForWrite();write_file();lock.unlock();...
}

QReadLocker和QWriteLocker

对于QReadWriteLock,qt也提供了类似于QMutexLocker的类,提供了对QReadWriteLock对象的托管,具体请见官方文档:

QReadLocker???QWriteLocker

QSemaphore

帮助文档:http://doc.qt.io/qt-5/qsemaphore.html

Qt提供的信号量,相比于互斥量只能锁定一次,信号量可以获取多次,它可以用来保护一定数量的同种资源,可用于对缓冲区的管理。

QSemaphore sem(5);      // sem.available() == 5
sem.acquire(3);         // sem.available() == 2
sem.acquire(2);         // sem.available() == 0
sem.release(5);         // sem.available() == 5
sem.release(5);         // sem.available() == 10
sem.tryAcquire(1);      // sem.available() == 9, returns true
sem.tryAcquire(250);    // sem.available() == 9, returns false

QWaitCondition

帮助文档:http://doc.qt.io/qt-5/qwaitcondition.html

提供了wait和wake方法,不光操作信号量还会主动唤醒其他线程,而且同一个变量可以控制多个线程,通过wakeone系统会随机唤醒一个等待的线程,通过wakeall会唤醒所有。此类不可单独使用需要配合QReadWriteLock或者QMutex,需要作为参数传递给QWaitCondition。

其他

线程结束后自动销毁的方法

connect(&thread, SIGNAL(finished()), &thread, SLOT(deleteLater()));

直接将线程结束的信号与deleteLater槽连接即可,deleteLater是QObject的槽函数

这篇关于Qt-多线程-QThread分析总结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1052186

相关文章

关于C++中的虚拟继承的一些总结(虚拟继承,覆盖,派生,隐藏)

1.为什么要引入虚拟继承 虚拟继承是多重继承中特有的概念。虚拟基类是为解决多重继承而出现的。如:类D继承自类B1、B2,而类B1、B2都继承自类A,因此在类D中两次出现类A中的变量和函数。为了节省内存空间,可以将B1、B2对A的继承定义为虚拟继承,而A就成了虚拟基类。实现的代码如下: class A class B1:public virtual A; class B2:pu

十五.各设计模式总结与对比

1.各设计模式总结与对比 1.1.课程目标 1、 简要分析GoF 23种设计模式和设计原则,做整体认知。 2、 剖析Spirng的编程思想,启发思维,为之后深入学习Spring做铺垫。 3、 了解各设计模式之间的关联,解决设计模式混淆的问题。 1.2.内容定位 1、 掌握设计模式的"道" ,而不只是"术" 2、 道可道非常道,滴水石穿非一日之功,做好长期修炼的准备。 3、 不要为了

[职场] 公务员的利弊分析 #知识分享#经验分享#其他

公务员的利弊分析     公务员作为一种稳定的职业选择,一直备受人们的关注。然而,就像任何其他职业一样,公务员职位也有其利与弊。本文将对公务员的利弊进行分析,帮助读者更好地了解这一职业的特点。 利: 1. 稳定的职业:公务员职位通常具有较高的稳定性,一旦进入公务员队伍,往往可以享受到稳定的工作环境和薪资待遇。这对于那些追求稳定的人来说,是一个很大的优势。 2. 薪资福利优厚:公务员的薪资和

Android多线程下载见解

通过for循环开启N个线程,这是多线程,但每次循环都new一个线程肯定很耗内存的。那可以改用线程池来。 就以我个人对多线程下载的理解是开启一个线程后: 1.通过HttpUrlConnection对象获取要下载文件的总长度 2.通过RandomAccessFile流对象在本地创建一个跟远程文件长度一样大小的空文件。 3.通过文件总长度/线程个数=得到每个线程大概要下载的量(线程块大小)。

人工智能机器学习算法总结神经网络算法(前向及反向传播)

1.定义,意义和优缺点 定义: 神经网络算法是一种模仿人类大脑神经元之间连接方式的机器学习算法。通过多层神经元的组合和激活函数的非线性转换,神经网络能够学习数据的特征和模式,实现对复杂数据的建模和预测。(我们可以借助人类的神经元模型来更好的帮助我们理解该算法的本质,不过这里需要说明的是,虽然名字是神经网络,并且结构等等也是借鉴了神经网络,但其原型以及算法本质上还和生物层面的神经网络运行原理存在

Java注解详细总结

什么是注解?         Java注解是代码中的特殊标记,比如@Override、@Test等,作用是:让其他程序根据注解信息决定怎么执行该程序。         注解不光可以用在方法上,还可以用在类上、变量上、构造器上等位置。 自定义注解  现在我们自定义一个MyTest注解 public @interface MyTest{String aaa();boolean bbb()

高度内卷下,企业如何通过VOC(客户之声)做好竞争分析?

VOC,即客户之声,是一种通过收集和分析客户反馈、需求和期望,来洞察市场趋势和竞争对手动态的方法。在高度内卷的市场环境下,VOC不仅能够帮助企业了解客户的真实需求,还能为企业提供宝贵的竞争情报,助力企业在竞争中占据有利地位。 那么,企业该如何通过VOC(客户之声)做好竞争分析呢?深圳天行健企业管理咨询公司解析如下: 首先,要建立完善的VOC收集机制。这包括通过线上渠道(如社交媒体、官网留言

tensorboard-----summary用法总结

Tensorflow学习笔记——Summary用法         最近在研究tensorflow自带的例程speech_command,顺便学习tensorflow的一些基本用法。 其中tensorboard 作为一款可视化神器,可以说是学习tensorflow时模型训练以及参数可视化的法宝。 而在训练过程中,主要用到了tf.summary()的各类方法,能够保存训练过程以及参数分布图并在

七种排序方式总结

/*2018.01.23*A:YUAN*T:其中排序算法:冒泡排序,简单排序,直接插入排序,希尔排序,堆排序,归并排序,快速排序*/#include <stdio.h>#include <math.h>#include <malloc.h>#define MAXSIZE 10000#define FALSE 0#define TRUE 1typedef struct {i

QT 中ListView和ListWidget有什么区别

ListView和ListWidget在Qt框架中都是用于显示列表数据的控件,但它们在使用方法和特性上存在一些明显的差异。以下是关于它们用法不一样的地方的详细分析: 数据管理方式: ListView:使用QAbstractItemModel数据模型来管理和显示列表数据。QAbstractItemModel是一个抽象类,允许开发者自定义数据模型以适应特定的数据结构和需求。这使得ListView在处