1. 介紹
QThread是Qt提供的線程類,每個QThread都可管理一個線程。html
其具備兩種使用方式:一、繼承爲QThread的子類;二、繼承爲QObject的子類,並使用QObject::moveToThread將此對象移到線程中運行多線程
QThread提供了以下基本函數:app
線程啓動:start()運行一次less
線程終止:terminate 終止線程,強制終止線程但會依據操做系統的調度策略,可能不是當即終止,最好用wait等待
quit退出線程,也能夠調用exit,效果相同,會正常終止線程。函數
線程狀態查詢:isRunning是否正在運行,isFinished是否運行完成測試
線程狀態信號:started線程啓動時發出,finished線程結束時發出ui
其餘:wait阻塞方式等待線程結束,調用此函數會將調用指令所在函數阻塞spa
建議對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對象的託管,具體請見官方文檔:
QReadLocker???QWriteLocker
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的槽函數