赞
踩
目录
1.前言
在Qt程序中,我们往往不满足于单一线程处理数据,在希望程序更高效更灵活的愿景下,我们都会尝试编写一个多线程的项目。要写一个多线程项目,就离不开QThread类型,这是Qt中创建的线程类型,当然在线程多的情况下还会引入线程池等,但那些都是后话。本篇文章将从源码的角度出发,简单的介绍QThread类从创建到消亡所执行的过程后,将重点分析源码刨析QThread的主要函数,分析在这些函数中都执行了什么操作。
QThread头文件链接https://codebrowser.dev/qt5/qtbase/src/corelib/thread/qthread.h.html#QThread
QThread源码链接https://codebrowser.dev/qt5/qtbase/src/corelib/thread/qthread.cpp.html#403
1.使用start()函数启动线程
2.调用Window中的API接口:CreateThread
3.调用QThreadDrivate::start()函数
4.emit thr->started(QThrad::QPrivateSignal())
5.thr->tun()
6.QThread::exce()
以上便是整个创建到消亡的流程,其中QThreadDrivate 是 Qt 中用于管理线程的类,允许您在不同的平台上使用相同的代码来创建和管理线程。
这些枚举量不是很常用,但是源码中使用enum声明为枚举量,主要是让我们创建的线程中存在优先级关系,方便处理优先级更高的线程(计算机操作系统中曾对线程优先级有所讲解,不懂可以去查查)
QThread::IdlePriority | 0 | 仅当没有其他线程运行时才调度 |
QThread::LowestPriority | 1 | 调度频率低于 LowPriority |
QThread::LowPriority | 2 | 调度频率低于 NormalPriority |
QThread::NormalPriority | 3 | 操作系统的默认优先级 |
QThread::HighPriority | 4 | 比 NormalPriority 更频繁地调度 |
QThread::HighestPriority | 5 | 比 HighPriority 安排得更频繁 |
QThread::TimeCriticalPriority | 6 | 尽可能频繁地安排 |
QThread::InheritPriority | 7 | 使用与创建线程相同的优先级。这是默认设置 |
下图为QThread类型的构造函数,其中:
1.Q_D(QThread)表示定义了类型为QThreadPrivate*的临时变量 d
,指向当前QThread对象的私有数据
2.d->data->thread.storeRelaxed(newValue:this):表示使用原子操作来安全地将当前线程与QThread对象关联起来
图1.QThread构造函数
下图为QThread类型的析构函数,其中:
1.QMutexLocker locker(&d->mutex):表示创建一个互斥锁并锁定QThread对象的内部互斥量,确保在析构函数执行期间对线程状态的访问是线程安全的
2.if(d->isInFinish):该条件中检查线程是否处于被销毁状态,处于则执行的代码为,第一释放互斥锁,第二等待线程完成,第三重新加锁互斥量,以继续进行析构过程(因为线程中的事件往往都是循环的,所以一般还需要析构)
3.if(d->runngin && !d->finishead && !d->data->isAdopted):该条件表示线程是否正在运行,是否未完成任务,是否未被管理。满足条件则发出警告
4.d->data->thread.storeRelease(newValue:nullptr):表示使用原子操作将d->data->thread指针设置为空指针,表明该线程已被销毁,不再与任何QThread对象关联
图2.QThread析构函数
下图为QThread类型的run函数,其中:
1.(void) exce():表示调用exce函数,然后将其返回值置为void类型,即无视返回对象
图3.QThread中run函数
下图为QThread类型的exce函数,该函数表示事件循环。其中:
1.d->data->quitNow = false:将quitNow标志重置为false,表示线程还没有退出
2.if(d->exited):表示如果线程已退出则返回代码
3.locker.unlock():表示释放互斥锁
4.QEventLoop:
表示创建一个新的事件循环对象
5.locker.relock():表示重新加锁,以确保后续操作线程安全
6.d->exited = flase 和 d->returnCode = -1:exited为false表示线程状态为未运行,returnCode为-1表示线程异常退出
图4.QThread中exec函数
下图为Thread类型的quit函数,其中:
1.exit():表示调用了exit函数,而exit函数恰巧也是线程终止函数,所以在程序中调用quit函数和exit函数终止线程并没有太多区别
图5.QThread中quit函数
下图为Thread类型中的exit函数,其中:
1.for(int i = 0; i< d->data->eventLoops.size(); ++i):该循环表示迭代所有的事件循环,并且调用事件循环的exit函数(有点回调函数的味道,哈哈),然后退出这些事件
图6.QThread中exit函数
下图为Thread类型中的terminate函数,其中:
1.if(!d->data->threadId.loadRelaxed()):该条件表示线程若未启动,则直接返回
2.int code = pthread_cancel(th:form_HANDLE<pthread_t>(id:d->data->threadId.loadRelaxed())):该代码表示调用底层的pthread_cancel函数来强制终止该线程
3.if(code):该条件表示如果调用pthread_cancel函数强制终止该线程失败,则报错
图6.QThread中terminate函数
Ps:一般不建议使用terminate()函数终止线程循环,如果线程中存在事件循环,调用terminate函数可能会导致程序崩溃
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。