博客地址已更改,文章數量較多不便批量修改,若想訪問源文請到 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函數設置優先級,優先級分為以下幾類:
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子類法
- //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獲取當前線程指針函數
2.2. 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;
- }
3. 線程同步
3.1. QMutex互斥量
通過lock,unlock實現加鎖、解鎖
使用tryLock嘗試加鎖,會返回加鎖成功與否,同時可設置超時時間。
注意在lock以后,任意return前必須進行unlock,否則會造成死鎖
3.2. 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;
- }
3.3. QReadWriteLock
使用QMutex無論對變量進行何種操作(讀寫)均會鎖定變量,而實際上對於讀取變量值並不需要等待,可以多個線程同時讀取,此時使用QReadWriteLock可以實現多線程讀,單線程寫的操作。幫助文檔
范例:
- QReadWriteLock lock;
- void ReaderThread::run() {
- ...
- lock.lockForRead();
- read_file();
- lock.unlock();
- ...
- }
- void WriterThread::run() {
- ...
- lock.lockForWrite();
- write_file();
- lock.unlock();
- ...
- }
3.4. QReadLocker和QWriteLocker
對於QReadWriteLock,qt也提供了類似於QMutexLocker的類,提供了對QReadWriteLock對象的托管,具體請見官方文檔:
3.5. QSemaphore
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
4. 其他
4.1. 線程結束后自動銷毀的方法
connect(&thread, SIGNAL(finished()), &thread, SLOT(deleteLater()));
直接將線程結束的信號與deleteLater槽連接即可,deleteLater是QObject的槽函數