版权声明:若无来源注明,Techie亮博客文章均为原创。 转载请以链接形式标明本文标题和地址:
本文标题:Qt多线程-QThread     本文地址:http://techieliang.com/2017/12/592/

1. 介绍

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

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

QThread提供了如下基本函数:

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

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

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

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

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

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

更多详细说明见官方文档

1.1. 线程优先级

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

Constant Value Description
QThread::IdlePriority 0 scheduled only when no other threads are running.
QThread::LowestPriority 1 scheduled less often than LowPriority.
QThread::LowPriority 2 scheduled less often than NormalPriority.
QThread::NormalPriority 3 the default priority of the operating system.
QThread::HighPriority 4 scheduled more often than NormalPriority.
QThread::HighestPriority 5 scheduled more often than HighPriority.
QThread::TimeCriticalPriority 6 scheduled as often as possible.
QThread::InheritPriority 7 use the same priority as the creating thread. This is the default.

1.2. 线程休眠

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

2. 基本使用

2.1. 建立QThread子类法

  1. //mythread.h
  2. #pragma once
  3. #include <QThread>
  4. #include <QDebug>
  5. class MyThread : public QThread {
  6. Q_OBJECT
  7. protected:
  8. void run() {
  9. while(1) {
  10. num++;
  11. qDebug()<<num<<"thread start:"<<QThread::currentThreadId();
  12. msleep(500);
  13. qDebug()<<num<<"thread end:"<<QThread::currentThreadId();
  14. }
  15. }
  16. private:
  17. int num = 0;
  18. };
  19. //main.cpp
  20. #include <QCoreApplication>
  21. #include <QThread>
  22. #include <QDebug>
  23. #include "mythread.h"
  24. int main(int argc, char *argv[]) {
  25. QCoreApplication a(argc, argv);
  26. qDebug()<<"Main:"<<QThread::currentThreadId();
  27. MyThread m;
  28. m.start();
  29. QThread::sleep(5);
  30. m.terminate();
  31. m.wait();
  32. return 0;
  33. }

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

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

2.2. moveToThread方法

  1. #pragma once
  2. #include <QThread>
  3. #include <QDebug>
  4. class MyThread : public QObject {
  5. Q_OBJECT
  6. public slots://注意要用槽函数
  7. void start() {
  8. qDebug()<<"thread end:"<<QThread::currentThreadId();
  9. }
  10. };
  11. #include <QCoreApplication>
  12. #include <QThread>
  13. #include <QDebug>
  14. #include "mythread.h"
  15. int main(int argc, char *argv[]) {
  16. QCoreApplication a(argc, argv);
  17. qDebug()<<"Main:"<<QThread::currentThreadId();
  18. QThread thread;
  19. MyThread m;
  20. m.moveToThread(&thread);
  21. QObject::connect(&thread,SIGNAL(started()),&m,SLOT(start()));
  22. thread.start();
  23. return 0;
  24. }

3. 线程同步

3.1. QMutex互斥量

帮助文档

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

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

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

3.2. QMutexLocker

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

帮助文档范例:

只是用QMutex的代码:

  1. int complexFunction(int flag) {
  2. mutex.lock();
  3. int retVal = 0;
  4. switch (flag) {
  5. case 0:
  6. case 1:
  7. retVal = moreComplexFunction(flag);
  8. break;
  9. case 2: {
  10. int status = anotherFunction();
  11. if (status < 0) {
  12. mutex.unlock();
  13. return -2;
  14. }
  15. retVal = status + flag;
  16. }
  17. break;
  18. default:
  19. if (flag > 10) {
  20. mutex.unlock();
  21. return -1;
  22. }
  23. break;
  24. }
  25. mutex.unlock();
  26. return retVal;
  27. }

使用QMutexLocker 代码

  1. int complexFunction(int flag) {
  2. QMutexLocker locker(&mutex);
  3. int retVal = 0;
  4. switch (flag) {
  5. case 0:
  6. case 1:
  7. return moreComplexFunction(flag);
  8. case 2: {
  9. int status = anotherFunction();
  10. if (status < 0)
  11. return -2;
  12. retVal = status + flag;
  13. }
  14. break;
  15. default:
  16. if (flag > 10)
  17. return -1;
  18. break;
  19. }
  20. return retVal;
  21. }

3.3. QReadWriteLock

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

范例:

  1. QReadWriteLock lock;
  2. void ReaderThread::run() {
  3. ...
  4. lock.lockForRead();
  5. read_file();
  6. lock.unlock();
  7. ...
  8. }
  9. void WriterThread::run() {
  10. ...
  11. lock.lockForWrite();
  12. write_file();
  13. lock.unlock();
  14. ...
  15. }

3.4. QReadLocker和QWriteLocker

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

QReadLocker???QWriteLocker

3.5. QSemaphore

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

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

4. 其他

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

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

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

Qt多线程-QThread的更多相关文章

  1. Qt 多线程QThread实现方法之一

    基本思想 在主线程中,哪里需用多线程,就在哪里创建一个QThread实例: 把耗时操作封装到一个继承于QObject的子类(这里叫做工作类Worker)槽函数中: 创建QThread实例和Worker ...

  2. Qt多线程-总结QThread-QThreadPool-QtConcurrent

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:Qt多线程-总结QThread-QThreadPool-QtConcurrent     本文 ...

  3. Qt 多线程和网络编程学习

    一,Qt多线程类学习 QThread类,开始一个新的线程就是开始执行重新实现QThread::run(),run()是默认现实调用exec(),QThread::start()开始线程的执行,run( ...

  4. Qt之QThread(深入理解)

    简述 为了让程序尽快响应用户操作,在开发应用程序时经常会使用到线程.对于耗时操作如果不使用线程,UI界面将会长时间处于停滞状态,这种情况是用户非常不愿意看到的,我们可以用线程来解决这个问题. 前面,已 ...

  5. [转] Qt 多线程学习

    Qt 多线程学习 转自:http://www.cnblogs.com/IT-BOY/p/3544220.html 最近的项目上用到了关于多线程的知识,自己也比较感兴趣,所以就拿了那本<C++ G ...

  6. 解析Qt中QThread使用方法

    本文讲述的是在Qt中QThread使用方法,QThread似乎是很难的一个东西,特别是信号和槽,有非常多的人(尽管使用者本人往往不知道)在用不恰当(甚至错误)的方式在使用QThread,随便用goog ...

  7. QT多线程笔记

    1.QT多线程涉及到主线程和子线程之间交互大量数据的时候,使用QThread并不方便,因为run()函数本身不能接受任何参数,因此只能通过信号和槽的交互来获取数据,如果只是单方面简单交互数据还过得去, ...

  8. Qt线程QThread简析(8个线程等级,在UI线程里可调用thread->wait()等待线程结束,exit()可直接退出线程,setStackSize设置线程堆栈,首次见到Qt::HANDLE,QThreadData和QThreadPrivate)

    QThread实例代表一个线程,我们可以重新实现QThread::run(),要新建一个线程,我们应该先继承QThread并重新实现run()函数. 需要注意的是: 1.必须在创建QThread对象之 ...

  9. Qt多线程-QtConcurrent并行运算高级API

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:Qt多线程-QtConcurrent并行运算高级API     本文地址:http://tec ...

随机推荐

  1. springboot 使用@ConfigurationProperties注入配置属性

    导入依赖,让springboot支持@ConfigurationProperties 注解 <!-- 支持 @ConfigurationProperties 注解 --> <depe ...

  2. dtree加载慢的问题

    前几天测试的时候,感觉dtree还行,也不是很慢.今天把树分支扩大以后就懵逼了,慢的一匹. 仔细看了下,才发现原来画分支的时候每次都会请求那些图,反复请求下加载时候无形拉长了很多.没有办法,就只能在h ...

  3. DotNetty学习笔记

    DotNetty项目本身的示例很容易运行起来,但是具体到真实的应用场景,还是需要进一步理解DotNetty的通道处理细节,这样才能够在实际项目应用中处理具体的问题. 简单的场景下会有以下几个问题,第一 ...

  4. 20155203 实验三《敏捷开发与XP实践》实验报告

    20155203 实验三<敏捷开发与XP实践>实验报告 一.实验内容 在IDEA中使用工具(Code->Reformate Code)把下面代码重新格式化,再研究一下Code菜单,找 ...

  5. 20155308 2016-2017-2《Java程序设计》课程总结

    20155308 2016-2017-2<Java程序设计>课程总结 每周作业链接汇总 预备作业1:回答"我专业吗.我的老师.师生关系.代码问题"四个问题. 预备作业2 ...

  6. 学号20155311 2016-2017-2《Java程序设计》课程总结

    学号20155311 2016-2017-2<Java程序设计>课程总结 (按顺序)每周作业链接汇总 预备作业1:(http://www.cnblogs.com/gaoziyun11/p/ ...

  7. 【整理总结】代码沉淀 - Caliburn.Micro - MV*模式短小精悍的框架

    Caliburn.Micro - Xaml made easy. web: https://github.com/Caliburn-Micro/Caliburn.Microdocument: http ...

  8. java开发划分级别的标准

    一.史诗序: java开发也有一段时间了,整天茫茫碌碌,除了偶尔的小有成就感,剩下的大部分好像都在重复,你是否也遇到了这样的情况? 遇到一个小细节问题,之前不久解决过,现在却是什么都记不起来了 面对每 ...

  9. Mybatis传递参数的三种方式

    第一种: Dao层使用@Param注解的方法 VersionBox getVersionByVersionNumAndVersionType(@Param("versionNum" ...

  10. 八、EnterpriseFrameWork框架基础功能之自定义报表

    本章写关于框架中的“自定义报表”,类似上章“字典管理”也是三部分功能组成,包括配置报表.对报表按角色授权.查看报表:其核心思想就是实现新增一个报表而不用修改程序代码.不用升级,只需要编写一个存储过程, ...