Qt中使用线程的几种方式及区别
概述
Qt中有多種創建線程的方式,每一種的應用場景和使用方式都有些區別, 這里主要簡單介紹Qt里面的幾大創建線程的方法,以及使用注意事項。
QThread
使用QThread創建線程是我們最常見的一種方式,步驟如下:
- 繼承QThread
- 重寫run()函數
- 通過start()函數啟動線程
優點:可以通過信號槽與外界進行通信。
缺點:①每次新建一個線程都需要繼承QThread,實現一個新類,使用不太方便。
②要自己進行資源管理,線程釋放和刪除。并且頻繁的創建和釋放會帶來比較大的內存開銷。
適用場景:QThread適用于那些常駐內存的任務。
輸出:
main id = 0x29a4 MyThread::run id = 0x1c2cQRunnable
前面一篇文章已經詳細介紹了QRunnable的使用方法【文章在這里】。 所以這里就不詳細描述了, 重點講一下優缺點和適用場景。
步驟如下:
- 繼承QRunnable。和QThread使用一樣, 首先需要將你的線程類繼承于QRunnable。
- 重寫run函數。還是和QThread一樣,需要重寫run函數,run是一個純虛函數,必須重寫。
- 使用QThreadPool啟動線程
優點:無需手動釋放資源,QThreadPool啟動線程執行完成后會自動釋放。
缺點:不能使用信號槽與外界通信。
適用場景:QRunnable適用于線程任務量比較大,需要頻繁創建線程。QRunnable能有效減少內存開銷。
具體代碼就不貼了,詳情參見上一篇文章。
moveToThread
moveToThread是在QThread的用法基礎上擴展出來的,它是QObject的接口,相對QThread線程方式來說,moveToThread使用更靈活,不需要繼承QThread,也不用重寫run函數。只需要將一個繼承于QObject的類通過moveToThread移到QThread的一個對象中。
需要注意的是:
- 只有在槽中執行的操作才是在線程中執行的,所以需要通過連接信號槽的方式來實現
- 如果object對象存在父對象,不能將其移到子線程中執行。
示例如下:
#include <QObject> #include <QThread>class Command : public QObject {Q_OBJECT public:explicit Command(QObject *parent = nullptr);void sendMessage(const QString &msg);signals:void sigMsg(QString msg);private slots:void onMessage(QString msg);private:QThread * m_pThread = nullptr; }; #include "command.h" #include <QDebug>Command::Command(QObject *parent) :QObject(parent) {m_pThread = new QThread();this->moveToThread(m_pThread);connect(this,&Command::sigMsg,this,&Command::onMessage);m_pThread->start();qDebug()<< __FUNCTION__ << " id = "<< QThread::currentThreadId(); }void Command::sendMessage(const QString &msg) {emit sigMsg(msg); }void Command::onMessage(QString msg) {qDebug()<< __FUNCTION__ << " id = "<< QThread::currentThreadId(); }調用:
m_pCommand = new Command(); //不能指定父類 m_pCommand->sendMessage("ABC");輸出:
Command::Command id = 0x4b58 Command::onMessage id = 0x3c84QtConcurrent::run
有關QtConcurrent::run的使用方法在之前的文章里面有詳細介紹過,在這里,Concurrent是并發的意思,QtConcurrent是一個命名空間,提供了一些高級的 API,使得在編寫多線程的時候,無需使用低級線程原語,如讀寫鎖,等待條件或信號。使用QtConcurrent編寫的程序會根據可用的處理器內核數自動調整使用的線程數。這意味著今后編寫的應用程序將在未來部署在多核系統上時繼續擴展。
QtConcurrent::run能夠方便快捷的將任務丟到子線程中去執行,無需繼承任何類,也不需要重寫函數,使用非常簡單。詳見前面的文章介紹,這里不再贅述。
需要注意的是,由于該線程取自全局線程池QThreadPool,函數不能立馬執行,需要等待線程可用時才會運行。
總結
以上是生活随笔為你收集整理的Qt中使用线程的几种方式及区别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Qt线程之QRunnable的使用详解
- 下一篇: Qt之QObjectCleanupHan