日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

Qt之QThreadPool和QRunnable

發(fā)布時(shí)間:2025/3/15 c/c++ 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Qt之QThreadPool和QRunnable 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.


簡(jiǎn)述

QRunnable 是所有 runnable 對(duì)象的基類,而 QThreadPool 類用于管理 QThreads 集合。

QRunnable 類是一個(gè)接口,用于表示一個(gè)任務(wù)或要執(zhí)行的代碼,需要重新實(shí)現(xiàn) run() 函數(shù)。

QThreadPool 管理和循環(huán)使用單獨(dú)的 QThread 對(duì)象,以幫助程序減少創(chuàng)建線程的成本。每個(gè) Qt 應(yīng)用程序都有一個(gè)全局 QThreadPool 對(duì)象,可以通過調(diào)用 globalInstance() 訪問。



詳細(xì)描述

QThreadPool 支持多次執(zhí)行相同的 QRunnable,通過調(diào)用 QThreadPool::tryStart(this) 從 run() 函數(shù)內(nèi)。如果啟用了 autoDelete,當(dāng)最后一個(gè)線程退出 run() 函數(shù),QRunnable 將被刪除。多次調(diào)用 QThreadPool::start() 使用相同的 QRunnable,當(dāng)啟用 autoDelete 時(shí)會(huì)創(chuàng)建一個(gè)競(jìng)爭(zhēng)條件,不推薦使用。

一定時(shí)間未使用線程將會(huì)到期,默認(rèn)到期超時(shí)是 30000 毫秒(30秒)。可以使用 setExpiryTimeout() 來改變,設(shè)定一個(gè)負(fù)值,則會(huì)禁用到期機(jī)制。

調(diào)用 maxThreadCount() 查詢使用線程的最大數(shù)量,如果需要,可以使用 setMaxThreadCount() 進(jìn)行更改。默認(rèn)情況下,maxThreadCount() 是 QThread::idealThreadCount()。activeThreadCount() 函數(shù)返回當(dāng)前正在工作線程的數(shù)量。

注意: QThread::idealThreadCount() 提供了計(jì)算程序運(yùn)行所在平臺(tái)上支持的輔助線程的最佳數(shù)量 - 考慮到操作系統(tǒng)、處理器的數(shù)量和機(jī)器擁有的處理核的數(shù)量。對(duì)于只有一個(gè)處理器、一個(gè)處理核的機(jī)器,該函數(shù)或許會(huì)返回 1。對(duì)于擁有多個(gè)處理器和處理核的機(jī)器,返回值則會(huì)相應(yīng)增大,這個(gè)數(shù)字不一定會(huì)與需要處理的文件個(gè)數(shù)完全匹配,因此需要將任務(wù)劃分,這樣的話,每個(gè)輔助線程(假設(shè)使用的輔助線程大于 1)都能得到一個(gè)和需要處理的文件數(shù)量相等的數(shù)值(當(dāng)然,用文件數(shù)量目來劃分任務(wù)或許不是在所有情況下都是最好的方法,例如:在一個(gè)數(shù)量為 20 的文件列表中,前 10 個(gè)文件很大,后 10 個(gè) 文件很小)。

reserveThread() 函數(shù)儲(chǔ)備一個(gè)線程用于外部使用。當(dāng)線程完成后,使用 releaseThread(),以便它可以被重新使用。從本質(zhì)上講,這些函數(shù)暫時(shí)增加或減少活躍線程的數(shù)量,并且當(dāng)實(shí)現(xiàn)耗時(shí)的操作時(shí)對(duì) QThreadPool 是不可見的,這比較有用。

注意: QThreadPool 是一個(gè)管理線程的低級(jí)類,高級(jí)替代品可以用 Qt Concurrent 模塊。

基本使用

要使用 QThreadPool 的一個(gè)線程,子類化 QRunnable 并實(shí)現(xiàn) run() 虛函數(shù)。然后創(chuàng)建一個(gè)對(duì)象,并把它傳遞給 QThreadPool::start() - 這會(huì)把可運(yùn)行對(duì)象的擁有權(quán)賦給 Qt 的全局線程池,并可以讓它開始運(yùn)行。

class HelloWorldTask : public QRunnable {void run() {qDebug() << "Hello world from thread " << QThread::currentThread();} }HelloWorldTask *hello = new HelloWorldTask();// QThreadPool取得所有權(quán),并自動(dòng)刪除 hello QThreadPool::globalInstance()->start(hello);

默認(rèn)情況下,當(dāng)可運(yùn)行對(duì)象結(jié)束時(shí),線程池會(huì)自動(dòng)將其刪除,這也正是我們想要的效果。在某些情況下,如果必須由我們自己負(fù)責(zé)刪除可運(yùn)行的對(duì)象時(shí),可以通過調(diào)用 QRunnable::setAutoDelete(false) 來阻止自動(dòng)刪除的發(fā)生。

自定義信號(hào)/槽

打開 QRunnable 所在頭文件,會(huì)發(fā)現(xiàn)它并不繼承自 QObject,也就是說,根本無法使用 QObject 的特性,例如:信號(hào)/槽、事件等。

為了便于使用,我們可以繼承 QObject:

class HelloWorldTask : public QObject, public QRunnable {Q_OBJECT// 自定義信號(hào) signals:void finished();public:void run() {qDebug() << "Hello Thread : " << QThread::currentThreadId();emit finished();} };

使用時(shí),連接信號(hào)槽即可:

class MainWindow : public QMainWindow {Q_OBJECTpublic:explicit MainWindow(QWidget *parent = 0): QMainWindow(parent){qDebug() << "Main Thread : " << QThread::currentThreadId();// ...HelloWorldTask *hello = new HelloWorldTask();connect(hello, SIGNAL(finished()), this, SLOT(onFinished()));QThreadPool::globalInstance()->start(hello);// ...}protected:void closeEvent(QCloseEvent *event) {if (QThreadPool::globalInstance()->activeThreadCount())QThreadPool::globalInstance()->waitForDone();event->accept();}private slots:void onFinished() {qDebug() << "SLOT Thread : " << QThread::currentThreadId();} };

為了獲得安全清楚,對(duì)于多線程應(yīng)用程序來說,最好在終止程序之前,停止所有輔助線程。我們已經(jīng)通過 closeEvent() 做到了這一點(diǎn),可以確保在允許終止動(dòng)作之前讓任何活動(dòng)的線程先結(jié)束掉。

順便再介紹下所屬線程,使用 qDebug 將各自的線程 ID 進(jìn)行調(diào)試輸出。結(jié)果如下:

Main Thread : 0xb308
Hello Thread : 0xb33c
SLOT Thread : 0xb308

顯然,槽函數(shù)所在線程與主線程相同。

如果想要槽函數(shù)在次線程中執(zhí)行,只需改變信號(hào)槽的連接方式:

connect(hello, SIGNAL(finished()), this, SLOT(onFinished()), Qt::DirectConnection);

這時(shí),就得到了想要的結(jié)果啦:

Main Thread : 0xb030
Hello Thread : 0xacf8
SLOT Thread : 0xacf8

事件的傳遞、數(shù)據(jù)的交互方式很多,這里只介紹了信號(hào)槽。當(dāng)然還可以使用自定義事件,然后通過 調(diào)用 QApplication::sendEvent() 或 QApplication::postEvent() 發(fā)送;或者使用 QMetaObject::invokeMethod() 方式均可,這里就不再贅述了。

總結(jié)

以上是生活随笔為你收集整理的Qt之QThreadPool和QRunnable的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。