QT多线程(QThread)小结

2023-11-10

QThread只有run函数是在新线程里的,其他所有函数都在QThread生成的线程里
如果QThread是在ui所在的线程里生成,那么QThread的其他非run函数都是和ui线程一样的,所以,QThread的继承类的其他函数尽量别要有太耗时的操作,要确保所有耗时的操作都在run函数里。 
在UI线程下调用QThread的非run函数(其实也不应该直接调用run函数,而应该使用start函数),和执行普通函数无区别,这时,如果这个函数要对QThread的某个变量进行变更,而这个变量在run函数里也会被用到,这时就需要注意加锁的问题,因为可能这个变量前几毫秒刚刚在run中调用,再调用时已经被另外的线程修改了。
安全结束线程:

https://blog.csdn.net/czyt1988/article/details/64441443


1.工作线程
每个程序启动后拥有的第一个线程称为主线程,即GUI线程。QT中所有的组件类和几个相关的类只能工作在GUI线程(是唯一允许执行GUI相关操作的线程),不能工作在次线程,次线程即工作线程,主要负责处理GUI线程卸下的工作,每个线程都有自己的栈

2.多线程简介
QT线程类包括:
QThread 提供了跨平台的多线程解决方案
QThreadStorage 提供逐线程数据存储
QMutex 提供相互排斥的锁,或互斥量
QMutexLocker 是一个辅助类,自动对 QMutex 加锁与解锁
QReadWriterLock 提供了一个可以同时读操作的锁
QReadLocker与QWriteLocker 自动对QReadWriteLock 加锁与解锁
QSemaphore 提供了一个整型信号量,是互斥量的泛化
QWaitCondition 提供了一种方法,使得线程可以在被另外线程唤醒之前一直休眠

3.线程优先级

4.线程的执行
void run() :线程体函数,定义线程的功能
void start() :启动函数,讲线程入口地址设置为run函数

5.线程的退出
void quit()
退出线程,返回0表示成功,相当于QThread:exit(0)
void exit( int returnCode = 0 ) : thread退出event loop,并从exec返回,exec的返回值就是        returnCode。通常returnCode=0表示成功,其他值表示失败
void terminate() : 强制结束线程,不保证数据完整和资源释放
setTerminationEnabled ( bool enabled = true ) : 打开terminate()

6.线程的等待
bool wait ( unsigned long time = ULONG_MAX ) : 线程将会被阻塞,等待time毫秒,如果线程退出,则wait会返回。Wait函数解决多线程在执行时序上的依赖
void sleep ( unsigned long secs ) 
void msleep ( unsigned long msecs )
void usleep ( unsigned long usecs )

7.线程的状态
isRunning() : 线程是否运行
isfinished() : 线程是否结束

8.线程与事件循环
QThread中run()的默认实现调用了exec(),从而创建一个QEventLoop对象,由QEventLoop对象处理线程中事件队列(每一个线程都有一个属于自己的事件队列)中的事件。exec()在其内部不断做着循环遍历事件队列的工作,调用QThread的quit()或exit()方法使退出线程,尽量不要使用terminate()退出线程,terminate()退出线程过于粗暴,造成资源不能释放,甚至互斥锁还处于加锁状态。


线程的同步:
1.同步基础
临界资源:每次只允许一个线程进行访问的资源
线程间互斥:多个线程在同一时刻都需要访问临界资源
线程锁能够保证临界资源的安全性,通常,每个临界资源需要一个线程锁进行保护。
线程死锁:线程间相互等待临界资源而造成彼此无法继续执行。
产生死锁的条件:
    A、系统中存在多个临界资源且临界资源不可抢占
B、线程需要多个临界资源才能继续执行
死锁的避免:
A、对使用的每个临界资源都分配一个唯一的序号
B、对每个临界资源对应的线程锁分配相应的序号
C、系统中的每个线程按照严格递增的次序请求临界资源
QMutex, QReadWriteLock, QSemaphore, QWaitCondition 提供了线程同步的手段。使用线程的主要想法是希望它们可以尽可能并发执行,而一些关键点上线程之间需要停止或等待。例如,假如两个线程试图同时访问同一个全局变量,结果可能不如所愿。

2.互斥量QMutex
QMutex 提供相互排斥的锁,或互斥量。在一个时刻至多一个线程拥有mutex,假如一个线程试图访问已经被锁定的mutex,那么线程将休眠,直到拥有mutex的线程对此mutex解锁。QMutex常用来保护共享数据访问。QMutex类所以成员函数是线程安全的。

头文件声明:    #include <QMutex>
互斥量声明:    QMutex m_Mutex;
互斥量加锁:    m_Mutex.lock();
互斥量解锁:    m_Mutex.unlock();
如果对没有加锁的互斥量进行解锁,结果是未定义的。互斥量的加锁和解锁必须在同一线程中成对出现。

    QMutex ( RecursionMode mode = NonRecursive )
    QMutex有两种模式:Recursive, NonRecursive
A、Recursive
    一个线程可以对mutex多次lock,直到相应次数的unlock调用后,mutex才真正被解锁。
B、NonRecursive
    默认模式,mutex只能被lock一次。
如果使用了Mutex.lock()而没有对应的使用Mutex.unlcok()的话就会造成死锁,其他的线程将永远也得不到接触Mutex锁住的共享资源的机会

bool tryLock();
如果当前其他线程已对该mutex加锁,则该调用会立即返回,而不被阻塞。
bool tryLock(int timeout);
如果当前其他线程已对该mutex加锁,则该调用会等待一段时间,直到超时

 

子类化QThread方式启动线程Demo

mythread.h

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QThread>
#include <QMutex>

class MyThread : public QThread
{
    Q_OBJECT
public:
    explicit MyThread(QObject *parent = 0);
    void startThread();             //开启线程
    void stop();                    //停止线程

protected:
    void run();                     //线程主执行函数

private:
    volatile bool stopped;          //线程停止位
    QMutex m_mutex;                 //互斥锁
};

#endif // MYTHREAD_H

mythread.cpp

#include "mythread.h"
#include <QDebug>

MyThread::MyThread(QObject *parent) :
    QThread(parent)
{
    stopped = false;
}

void MyThread::run()
{
    qreal i = 0;
    while (!stopped) 
    {
        qDebug() << QString("in MyThread: %1").arg(i);
        msleep(1000);
        i++;
    }
}

void MyThread::startThread()
{
    m_mutex.lock();
    stopped = false;
    m_mutex.unlock();
    start();
}

void MyThread::stop()
{
    m_mutex.lock();
    stopped = true;
    m_mutex.unlock();
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

QT多线程(QThread)小结 的相关文章

随机推荐

  • 211院校计算机考研难度排名,全国211院校考研难度详细分析!建议收藏!

    原标题 全国211院校考研难度详细分析 建议收藏 很多考研的童鞋 都是为了提升自己的学历而来 梦想着考取名校 圆自己一个名校梦 希望是光明的 道路是曲折的 通向名校的道路 往往竞争十分惨烈 帮大家分析各大高校的考研难度 让小伙伴们能在考研之
  • C++ C#自动获得特定串口 获得串口列表

    目的 自动获得特定串口 0 C 自动获得特定串口 读设备管理器 计算机管理 串口列表 PrintDeviceInfo cpp 定义控制台应用程序的入口点 include
  • 人工智能学习----Pandas进阶及统计分析

    人工智能学习 Pandas进阶及统计分析 目录 一 基本数据对象及操作 二 数据清洗 三 数据合并及分组 四 透视表 目录 基本数据对象及操作 数据清洗 数据合并及分组 透视表 一 基本数据对象及操作 1 Series 类似一维数组的对象
  • Java实现Excel转PDF的两种方法总结

    hello 你好呀 我是灰小猿 一个超会写bug的程序猿 使用具将Excel转为PDF的方法有很多 在这里我给大家介绍两种常用的方法 分别应对两种不一样的使用场景 接下来我在springboot环境下给大家做一下演示 一 使用spire转化
  • 低成本运行 Spark 数据计算

    作者 柳密 阿里巴巴阿里云智 导读 本节课主要介绍如何在 Serverless Kubernetes 集群中低成本运行 Spark 数据计算 首先简单介绍下阿里云 Serverless Kubernetes 和 弹性容器实例 ECI 这两款
  • HDU2035(附所用数论中的性质推导及快速模运算的递归形式)

    Problem Description 求A B的最后三位数表示的整数 说明 A B的含义是 A的B次方 Input 输入数据包含多个测试实例 每个实例占一行 由两个正整数A和B组成 1 lt A B lt 10000 如果A 0 B 0
  • RDD转化为DataFrame的两种方法

    目录 前言 一 DataFrame的创建 从数据源创建 二 RDD gt DataFrame 1 利用反射机制推断RDD模式 2 使用编程方式定义RDD模式 前言 为什么要推出DataFrame DataFrame的推出 让Spark具备了
  • android 多层json,Android json解析:根据嵌套key值逐层获取最底层数据

    需求 根据预先定义好的嵌套的key值一层层获取json最底层数据 主函数里的代码 String json1 code 0 data cid cstatus 1 doc 1 docsProtocolRead 0 funcSwitch 1 ha
  • 使用URL打开文件夹

    示例 打开资产目录 需要加前缀 Application OpenURL file folderPath 推荐使用Uri类 会将路径进行转换 var folderPath Application dataPath var uri new Ur
  • 学习制作AI语言模型需要准备...,你看懂了哪些?

    制作AI语言模型主要需要以下几个方面的准备 数据集 制作AI语言模型的关键是要有大量的数据进行训练 越多的数据意味着模型越准确 数据集可以来自于已有的文本资料 互联网上的文章 新闻 社交媒体上的评论 对话等等 算法 AI语言模型的核心是算法
  • 【C++】STL-函数对象-内建函数对象

    0 前言 1 算术仿函数 include
  • Java获取前端不同请求方式的参数

    文章目录 一 前言 1 请求类型 2 数据提交方式 二 不同请求方式参数的获取 1 get ms 2 get 路径参数 3 post ms 4 post data 一 前言 随着前端后端分离项目的普及 一些单体架构的项目也渐渐退出舞台 本篇
  • vue 开发常用插件

    列举了Vue开发中的常用vscode插件 Tabnine 是一款AI自动补全插件 在日常开发中能节省20 左右手动补全代码的时间
  • MySQL巧妙利用help_topic表把以逗号分隔的字符串转换成行

    MySQL巧妙利用help topic表把以逗号分隔的字符串转换成行 脚本 select substring index substring index 82 83 84 85 86 help topic id 1 1 as Id from
  • linux编译运行c++多线程程序

    引言 Linux下编译运行普通的C 程序此前已有文章介绍不再累述 下文主要介绍Linux下如何编译多线程的c 程序 正文 首先尝试编译 cpp文件 例中文件名test2 cpp 执行 g test2 cpp 后可看到编译不通过 报了许多错
  • 解决Could not install packages due to an EnvironmentError: [WinError 5] 拒绝访问。(win10下升级pip)

    一 问题描述 在dos下升级pip时 报错如下 Could not install packages due to an EnvironmentError WinError 5 拒绝访问 c program files python37 l
  • 081基于深度学习的农业病虫害检测小程序版本

    卷积网路CNN分类的模型一般使用包括alexnet DenseNet DLA GoogleNet Mobilenet ResNet ResNeXt ShuffleNet VGG EfficientNet和Swin transformer等1
  • 欧姆龙温控器参数笔记(五)(高级功能设定菜单)

    要进入这个菜单是需要输入密码的 密密麻麻的 但是大多是重复的 比如关于报警 关于输出分配 项目显示 重点 比如这里选择o 温控器就控制ssr来进行加热 比如这里可以sub1设为run sub2设为ha 这个时候 温控器工作的时候 输出sub
  • opencv--图像金字塔--高斯金字塔

    什么是图像金字塔 我们需要了解一个概念 尺度 尺度 顾名思义就是说图像的尺寸和分辨率 在我们进行图像处理的时候 会经常对源图像的尺寸进行放大或者缩小的变换 进而转换为我们指定尺寸的目标图像 在对图像进行放大和缩小的变换的这个过程 我们称为尺
  • QT多线程(QThread)小结

    QThread只有run函数是在新线程里的 其他所有函数都在QThread生成的线程里 如果QThread是在ui所在的线程里生成 那么QThread的其他非run函数都是和ui线程一样的 所以 QThread的继承类的其他函数尽量别要有太