zoukankan      html  css  js  c++  java
  • Qt多线程-QThread

    博客地址已更改,文章数量较多不便批量修改,若想访问源文请到 coologic博客 查阅,网址:www.coologic.cn

    如本文记录地址为 techieliang.com/A/B/C/ 请改为 www.coologic.cn/A/B/C/ 即可查阅

    版权声明:若无来源注明,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函数设置优先级,优先级分为以下几类:

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

    使用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.  
    10. void WriterThread::run() {
    11. ...
    12. lock.lockForWrite();
    13. write_file();
    14. lock.unlock();
    15. ...
    16. }

    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的槽函数

  • 相关阅读:
    NSString
    IOS
    IOS
    UITextView
    UIButton
    IOS 视频缩略图的生成
    IOS CALayer的阴影属性
    IOS 创建渐变图层
    IOS 截取图片 部分 并生成新图片
    [看远、看透、看淡]
  • 原文地址:https://www.cnblogs.com/techiel/p/8013018.html
Copyright © 2011-2022 走看看