目錄
1.1 qthread使用方法
1.2 qsemaphore使用方法
1.3 qwaitcondition使用方法
1.4 qthreadpool使用方法
1.5 qtconcurrent使用方法
前言:目前專案中使用到qsemaphore來構建執行緒池,之前只是簡單使用qthread類,這裡系統記錄多執行緒的基本使用,方便後面使用到的時候翻開回憶,不再到處搜尋知識點。「建立」乙個新執行緒,等待 cpu 來執行;當 cpu 來執行時,如果該執行緒需要等待另外某個事件被執行完後才能執行,那該執行緒此時是處於「阻塞」狀態;如果不需要等待其他事件,執行緒就可以被「執行」了,也可以稱為正在占用時間片;時間片用完後,執行緒會處於「就緒」狀態,等待下一次時間片的到來;所有任務都完成後,執行緒就會進入「退出」狀態,作業系統就會釋放該執行緒所分配的資源。
執行緒同步:所謂協同步調,即多個執行緒打配合完成某項複雜工作。執行緒同步涉及的技術有執行緒鎖(互斥物件mutex),條件變數(condition)和訊號量(semaphore)。
qt中提供了三種在主線程之外建立工作執行緒的方法:1. 繼承qthread;2.繼承qobject,然後使用movetothread(qthread * targetthread)將物件移動到工作執行緒中執行;3.繼承qrunnable,並將建立的物件移動到qthreadpool中進行執行。
qt官方建議僅僅在需要擴充套件qthread本身的功能時使用第一種方法,而執行一般的工作時可使用第2種或第3種方法。後兩者的區別是第2種方法可以通過訊號進行執行緒間的通訊。qrunnable沒有繼承qobject,適合執行不關心執行進度或者不需要在中間環節進行控制的方法。
qthread
繼承qobject
.。它可以傳送started和finished訊號,也提供了一些slot函式。
qobject
可以用於多執行緒,可以傳送訊號呼叫存在於其他執行緒的slot函式,也可以postevent給其他執行緒中的物件。之所以可以這樣做,是因為每個執行緒都有自己的事件迴圈
qthread 的執行入口函式是run(),從該函式返回將結束執行緒;wait()函式是等待run()函式執行結束並返回,此時wait()返回值為true;建立執行緒的方法有兩種,1.直接繼承qthread; 2.使用qobject::movetothread()將 qobject 物件移到新開的 qthread 執行緒物件中,這樣 qobject 物件中所有的耗時操作都會在新執行緒中被執行。
class worker : public qobject
signals:
void resultready(const qstring &result);
}; class controller : public qobject
~controller()
public slots:
void handleresults(const qstring &);
signals:
void operate(const qstring &);
};
qthread的介面函式:
qthread(qobject* parent=0);new乙個qthread,父類有qthread的所有權,通過start()啟動執行緒
~qthread ()銷毀執行緒,在銷毀執行緒前等待finished()訊號
exit ( int returncode = 0 )告訴執行緒的事件迴圈通過返回碼離開,returncode=0表示success
isfinished()const,isrunning()const返回是否結束和是否執行
priority priority () const返回執行緒執行的優先順序,如果執行緒沒執行返回7
setpriority ( priority priority )設定執行緒優先順序
setstacksize ( uint stacksize )設定最大執行緒堆疊,如果不設定由作業系統自動分配,且stacksize()返回0
wait( unsigned long time = ulong_max )如果是預設值則wait()將不會超時
void quit ()告訴執行緒的事件迴圈退出並且返回0值
void start ( priority priority = inheritpriority )以某種優先順序開啟乙個執行緒
void terminate ()終止當前執行緒。執行緒或許不會立即被終止,依賴於執行緒的排程策略
bool isstopthread = false;
class athread:public qthread
void run()
if(keyevent->key () == qt::key_b)
//keypressevent (keyevent);
}
「程序的建立、撤銷與切換存在著較大的時空開銷」,因此出現了執行緒這種輕量級程序技術。如果還想進一步的降低系統資源開銷,人們想出了乙個辦法,就是讓執行完所有任務的執行緒不被銷毀,讓它處於「待命」的狀態等待新的耗時操作「進駐」進來。qt 提供了 qthreadpool 和 qrunnable 這兩個類來對執行緒進行重複的使用。使用的方法一般是將耗時操作放入qrunnable 類的 run() 函式中,然後整體把 qrunnable 物件扔到 qthreadpool 物件中就可以了。任務的統一封裝形式:qrunnableqrunnalbe:能用到執行緒池的任務,基本上功能單一且並不需要和其他執行緒進行訊號槽的通訊
引用:
qrunnable()
virtual ~qrunnable()
bool autodelete() const
void setautodelete(bool autodelete)
virtual void run() = 0
只需要繼承qrunnable並且重寫run函式,扔給執行緒池即可
class helloworldtask : public qrunnable};
helloworldtask *task = new helloworldtask();
qthreadpool::globalinstance->start(task);
qthreadpool只有執行緒qthread和任務qrunnable兩種資料容器來管理任務排程,執行緒池的本質就是協調兩種容器之間資料的互動。執行緒池中的執行緒也進行了二次封裝,由繼承於 qthread 的 qthreadpoolthread 類表示。該類在 qthread 的基礎上擴充套件了兩個私有變數:qrunnable * 和 qthreadpoolprivate *,乙個用於儲存當前執行緒要執行的任務,乙個用於儲存執行緒池的指標。
因為每個 qt 程式或者說每個程序都有乙個全域性 qthreadpool 物件,所以 globalinstance() 函式用於獲取該物件的指標,那麼用的時候直接用該靜態函式即可,顯式的建立乙個區域性執行緒池也是可以的。
};int main(int argc, char *ar**)
//顯示建立
}};int main(int argc, char *ar**)
return a.exec();
}
qthread 這種很底層的類,使用起來要考慮方方面面,用到底層的介面(如 qthread、訊號量、互斥鎖等),另外qt 提供了高階函式來簡化多執行緒編寫,qt concurrent 。
//pro 檔案新增「qt += concurrent」並且在我們的 h 檔案新增「#include 」
int main(int argc, char *ar**)
//傳參
extern void afunction(int arg1, double arg2, const qstring &string);
int a = 1;
double b = 2;
qstring string = "hello";
qtconcurrent::run(afunction, a, b, string);
//返回值
extern qstring function();
qfuturenfuture = qtconcurrent::run(function);
qstring result = future.result();
參考:
如何正確使用qthread
QT執行緒(一) 執行緒類
執行緒之間共享資料,但又單獨執行 qt執行緒 qthread 是平台無關的 通常主線程從 main 開始執行,而在主線程中建立其他執行緒,其他執行緒派生於 qthread 1 執行緒優先順序總共8 個優先順序 執行緒優先順序從上到下越來越高。constant value description qt...
QT執行緒(一) 執行緒類
執行緒之間共享資料,但又單獨執行 qt執行緒qthread是平台無關的 通常主線程從main開始執行,而在主線程中建立其他執行緒,其他執行緒派生於qthread 1 執行緒優先順序 總共8個優先順序 執行緒優先順序從上到下越來越高。constant value description qthread...
細說qt多執行緒(一)
眾所周知,qt 建立多執行緒有主流的有3種方法 1.採用經典的qthread類。2.實現qrunable 介面。3.採用qt並行框架qtconcurrent。既然有三種方法,那麼哪種方式更好,在實際的專案中改採取哪種方式來實現?那麼我們不得不對3種方式做下對比。下面我將對每 一種方式,表達下我的淺見...