1. 程式人生 > >QT執行緒池實驗研究與分析(QThread與和QThreadPool + QRunnable使用上的區別)

QT執行緒池實驗研究與分析(QThread與和QThreadPool + QRunnable使用上的區別)

第一部分:QT執行緒池的構建與使用

    網上關於QT執行緒池QThreadPool的文章很多,而且大都千篇一律,基本上都是參考QT的幫助文件介紹QT全域性執行緒池的用法。這樣就往往會使人產生誤解,QT是不是推薦大家使用其全域性執行緒池,而不推薦使用自定義構造的執行緒池? 實際情況並不是這樣的。而且在實際的專案當中我們通常並不希望僅僅使用一個全域性的執行緒池,而是在需要執行緒池的工程中都構建和維護自己一個小小的執行緒池(我們知道一個良好架構的專案通常是由多個工程組成的)。綜上,我們來分析以下兩個問題:

    (1)    非全域性的執行緒池如果構建與使用呢?

#include <QObject>
#include <QRunnable>
#include <QThread>
#include <QThreadPool>
#include <QDebug>
class HelloWorldTask : public QRunnable
{
     // 執行緒執行任務:每間隔1s打印出執行緒的資訊
	void run()
	{
	    for (int nCount = 0; nCount < 5; nCount++)
	    {
		qDebug() << QThread::currentThread();
		QThread::msleep(1000);
	    }
	}
};
int main(int argc, char *argv[])
{
	QCoreApplication a(argc, argv);

	QThreadPool	  threadpool;	           // 構建一個本地的執行緒池
	threadpool.setMaxThreadCount(3);         // 執行緒池中最大的執行緒數
      	for (int nNum = 0; nNum < 100; nNum++)
	{
	    HelloWorldTask	 *task;    // 迴圈構建可線上程池中執行的任務
	    threadpool.start(task);      //執行緒池分配一個執行緒執行該任務
	    QThread::msleep(1000);
	}
	return a.exec();
}

    上述程式,構建了一個執行緒最大數量為3的本地執行緒池。每間隔1s的時間建立一個執行緒任務並置入到執行緒池的任務佇列中(QT內部機制實現該佇列,我們只需要呼叫QThreadPool的start函式置入即可)。每個執行緒任務的持續時間為5s。

    (2)    程式當中QRunnable是以指標的形式建立的,該指標是需要程式設計師去釋放,還是QThreadPool在執行完執行緒後自動釋放?

    解答:在上述例子當中,我們建立的QRunnable型別的指標 QRunnable *task 是不需要我們手動去回收記憶體的,QThreadPool在結束該任務的執行後會將對該記憶體進行清空。

    上述解答並不是憑空猜測,一方面根據是QT文件中的一句話:

    QThreadPool takes ownership and deletes 'hello'automatically

     用直白的話說就是:QThreadPool會佔有這個指標的控制代碼並在執行結束後釋放指標所佔的記憶體。

    另一方面,我們也通過改進上面的例子進行驗證。

#include <QObject>
#include <QRunnable>
#include <QThread>
#include <QThreadPool>
#include <QDebug>
class HelloWorldTask : public QRunnable
{
     // 執行緒執行任務:每間隔1s打印出執行緒的資訊
	void run()
	{
            int         m_dataMem[256*1000];		          // 佔約 1MB記憶體空間 
	    for (int nCount = 0; nCount < 5; nCount++)
	    {
		qDebug() << QThread::currentThread();
		QThread::msleep(1000);
	    }
	}
};
int main(int argc, char *argv[])
{
	QCoreApplication a(argc, argv);

	QThreadPool	  threadpool; 
	threadpool.setMaxThreadCount(1); 
      	for (int nNum = 0; nNum < 100; nNum++)
	{
	    HelloWorldTask	 *task; 
	    threadpool.start(task); 
	    QThread::msleep(1000);
	}
	return a.exec();
}

     在程式執行過程中,我們觀察發現程式的程序一直僅佔用約1MB的記憶體空間。如果在main函式中所建立的100個HelloWorldTask 指標物件沒有被QThreadPool釋放的話,隨著程式的執行該程式所佔記憶體空間應該逐步攀升到約100MB。然而實際情況是,該程式最高僅佔用1MB的記憶體空間。

    綜上兩個方面可以得出以下結論:QRunnable建立的物件QThreadPool在執行完該物件後會幫助我們來清空記憶體,不需要我們手動回收記憶體。

第二部分:QThread 與QRunnable + QThreadPool適用的應用場景

    QThread是QT的執行緒類,通過繼承QThread然後重寫run函式即可實現一個執行緒類。QThreadPool+ QRunnable配合構建執行緒池的方法也可以實現執行緒。我們通過以下問題對上述兩種構建執行緒的方法進行分析和說明。

    (1)既然QThread這麼簡單我們為什麼還要使用QThreadPool + QRunnable建立執行緒池的方法來使用執行緒機制呢?

主要原因:當執行緒任務量非常大的時候,如果頻繁的建立和釋放QThread會帶來比較大的記憶體開銷,而執行緒池則可以有效避免該問題,相關的基礎支援可以自行百度執行緒池的優點。

    (2)QThread與 QThreadPool + QRunnable分別適用於哪種應用場景?

     QThread適用於那些常駐記憶體的任務。而且QThread可以通過訊號/槽的方式與外界進行通訊。而QRunnable則適用於那些不常駐記憶體,任務數量比較多的情況。

第三部分:QRunnable 如何與外界進行通訊

       方法1:QRunnable並不繼承自QObject類,因此無法使用訊號/槽的方式與外界進行通訊。我們就必須的使用其他方法,這裡給大家介紹的是使用:QMetaObject::invokeMethod()函式。

       方法2:使用多重繼承的方法,任務子類同時繼承自QRunnable和QObject。

      歡迎交流討論 

      QQ 33845995  

      Email : [email protected]

阿科

2016年6月18日 於森林半島

相關推薦

QT執行實驗研究分析QThreadQThreadPool + QRunnable使用區別

第一部分:QT執行緒池的構建與使用     網上關於QT執行緒池QThreadPool的文章很多,而且大都千篇一律,基本上都是參考QT的幫助文件介紹QT全域性執行緒池的用法。這樣就往往會使人產生誤解,QT是不是推薦大家使用其全域性執行緒池,而不推薦使用自定義構造的執行緒池?

Java執行之ThreadPoolExecutor原始碼分析

一、引言 Java併發工具包自帶了很多常用的執行緒池,程式可以將定義的Runnable、Callable任務提交到執行緒池當中執行,由執行緒池負責非同步執行其中的任務。 Java執行緒池框架結構圖: 其中,Executors是一個執行緒池靜態工廠類,可以呼叫其

jdk自帶的執行框架ThreadPoolExcutor原始碼分析

一、前言   JUC這部分還有執行緒池這一塊沒有分析,需要抓緊時間分析,下面開始ThreadPoolExecutor,其是執行緒池的基礎,分析完了這個類會簡化之後的分析,執行緒池可以解決兩個不同問題:由於減少了每個任務呼叫的開銷,它們通常可以在執行大量非同步任務

使用執行來實現AsyncTask的排隊機制拒絕策略

用imageview來實現海報牆,用ArrayBlockingQueue和ThreadPoolExecutor.DiscardOldestPolicy()來實現海報牆http請求的執行緒池的排隊策略:

Java併發4深入分析java執行框架及實現原理

先說說我個人對執行緒池的理解:執行緒池顧名思義是一個裝有很多執行緒的池子,這個池子維護著從執行緒建立到銷燬的怎個生命週期以及執行緒的分配,使用者只需要把任務提交給這個執行緒池而不用去關心執行緒池如何建立執行緒,執行緒池會自己給這些任務分配執行緒資源來完成任務。 java的E

QT 執行 + TCP 小試實現通訊功能

*免分資源連結點選開啟連結http://download.csdn.net/detail/goldenhawking/4492378         有了執行緒池,我們下一步就利用 QTcpServer 搭建一個伺服器,接受客戶端的連線,並把資料傳送到執行緒池上。由於 QT

幾種執行的實現演算法分析

1. 前言 在閱讀研究執行緒池的原始碼之前,一直感覺執行緒池是一個框架中最高深的技術。研究後才發現,執行緒池的實現是如此精巧。本文從技術角度分析了執行緒池的本質原理和組成,同時分析了JDK、Jetty6、Jetty8、Tomcat的原始碼實現,對於想了解執行緒池本質、更

JUC(4)---java執行原理及原始碼分析

執行緒池,既然是個池子裡面肯定就裝很多執行緒。 如果併發的請求數量非常多,但每個執行緒執行的時間很短,這樣就會頻繁的建立和銷燬 執行緒,如此一來會大大降低系統的效率。可能出現伺服器在為每個請求建立新執行緒和銷燬線 程上花費的時間和消耗的系統資源要比處理實際的使用者請求的時間和資源更多。因此Java中提供執行緒

Java併發二十一執行實現原理 Java併發十八:阻塞佇列BlockingQueue Java併發十八:阻塞佇列BlockingQueue Java併發程式設計:執行的使用

一、總覽 執行緒池類ThreadPoolExecutor的相關類需要先了解:  (圖片來自:https://javadoop.com/post/java-thread-pool#%E6%80%BB%E8%A7%88) Executor:位於最頂層,只有一個 execute(Runnab

-1-5 java 多執行緒 概念 程序 執行緒區別聯絡 java建立執行緒方式 執行緒執行緒池概念 執行緒安全 同步 同步程式碼塊 Lock鎖 sleep()wait()方法的區別 為什麼wait(),notify(),notifyAll()等方法都定義在O

 本文關鍵詞: java 多執行緒 概念 程序 執行緒區別聯絡 java建立執行緒方式 執行緒組 執行緒池概念 執行緒安全 同步 同步程式碼塊 Lock鎖  sleep()和wait()方法的區別 為什麼wait(),notify(),notifyAll()等方法都定義在Object類中 多執行緒

opencv人臉檢測程式碼應用分析PC端Android端

(1)OpenCV人臉檢測C++程式流程: OpenCV的人臉檢測程式採用了Viola & Jones人臉檢測方法,主要是呼叫訓練好的瀑布級聯分類器cascade來進行模式匹配。 cvHaarDetectObjects先將影象灰度化,根據傳入引數判斷是否進行can

gcc編譯執行程式需帶-lpthread選項否則出錯:undefined reference to `pthread_create'

程式中兩處使用了pthread_create函式,包含了標頭檔案#include <pthread.h>。 gcc xxx.c -o xxx 編譯時出現以下錯誤: 分析: 用gcc編譯使用了POSIX thread的程式時通常需要加額外的選項,以連結到庫。 此

Qt執行-QThreadPool執行QRunnable

介紹 執行緒的建立及銷燬需要與系統互動,會產生很大的開銷。若需要頻繁的建立執行緒建議使用執行緒池,有執行緒池維護一定數量的執行緒,當需要進行多執行緒運算時將運算函式傳遞給執行緒池即可。執行緒池會根據可用執行緒進行任務安排。 QThreadPool 此類為Qt提供

深入理解Java執行原理分析使用尤其當執行佇列滿了之後事項

在這裡借花獻佛了,那別人的東西學一學了。在我們的開發中“池”的概念並不罕見,有資料庫連線池、執行緒池、物件池、常量池等等。下面我們主要針對執行緒池來一步一步揭開執行緒池的面紗。使用執行緒池的好處1、降低資源消耗可以重複利用已建立的執行緒降低執行緒建立和銷燬造成的消耗。2、提高響應速度當任務到達時,任務可以不需

執行的使用分析

一 關於 ThreadPoolExecutor 轉載: https://www.cnblogs.com/dolphin0520/p/3932921.html 糾正: 1.在jdk1.8中,標識執行緒狀態的runState,用 AtomicInteger ctl 來表示。 &nbs

執行執行佇列分析-優

·  執行緒池是物件池的一個有用的例子,它能夠節省在建立它們時候的資源開銷。並且執行緒池對系統中的執行緒數量也起到了很好的限制作用。 ·  執行緒池中的執行緒數量必須仔細的設定,否則冒然增加執行緒數量只會帶來效能的下降。 ·  在定製ThreadPoolExecutor時,

Android通過AsyncTaskThreadPool執行兩種方式非同步載入大量資料的分析對比

如果您認為本部落格不錯,讀後覺得有收穫,不妨打賞讚助我一下,讓我有動力繼續寫出高質量的部落格。 贈人玫瑰,手有餘香。分享技術,傳遞快樂。 有心課堂,傳遞的不僅僅是技術! QQ交流群:250468947 有心課堂會員,請加入VIP QQ交流

Tensorflow 原始碼分析-會話執行之間的關係

1. Tensorflow 的sessionFactory建立新的會話,tensorflow使用了多工廠模式,在不同的場景下使用不同的工廠, 使用什麼工廠模式由傳遞進來的SessionOptions來決定。1.1 註冊工廠Tensorflow 提供了可以註冊多會話工廠的模式,

JAVA執行ThreadPoolExecutor原理分析使用

在我們的開發中,“池”的概念並不罕見,有資料庫連線池、執行緒池、物件池、常量池等。下面我們主要針對執行緒池來一步一步揭開執行緒池的面紗。 使用執行緒池的好處 (1)降低資源消耗 可以重複利用自己建立的執行緒降低執行緒建立和銷燬造成的消耗。 (2)提高響應速度 當任務到達時

執行的使用分析ThreadPoolExcutors

開發中為什麼使用執行緒池1.降低資源的消耗:通過重複利用已經建立好的執行緒降低執行緒的建立和銷燬帶來的損耗2.提高響應速度:因為執行緒池中的執行緒數沒有超過執行緒池的最大上限時,有的執行緒處於等待分配任務的狀態,當任務來時無需建立新的執行緒就能執行3.提高執行緒的可管理性:執