Qt多線程-QThread

版權聲明:若無來源註明, Techie亮博客文章均爲原創。 轉載請以連接形式標明本文標題和地址:
本文標題:Qt多線程-QThread     本文地址: http://techieliang.com/2017/12/592/

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子類法

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

相關文章
相關標籤/搜索