源地址:http://blog.csdn.net/liuhongwei123888/article/details/6072320
Qt 是一種基於 C++ 的跨平臺 GUI 系統,能夠提供給使用者構造圖形使用者介面的強大功能。為了滿足使用者構造複雜圖形介面系統的需求,Qt 提供了豐富的多執行緒程式設計支援。Qt 主要從三個方面對多執行緒程式設計提供支援:一、構造了一些基本的與平臺無關的執行緒類;二、提交使用者自定義事件的 Thread-safe 方式;三、多種執行緒間同步機制,如訊號量,全域性鎖。
1、QThread
QThread提供了與平臺無關的執行緒。一個QThread代表單獨運行於程式的執行緒。它與程序中的其他執行緒共享資料,在多工作業系統中單獨執行。執行緒使用run()方法開始執行,在run()方法中呼叫exec()開始事件迴圈。我們可以通過繼承QThread並且重寫run()函式編寫一個執行緒。例如:
- //mythread.h
- #ifndef MYTHREAD_H
- #define MYTHREAD_H
- #include <QThread>
- class MyThread : public QThread
- {
- public:
- MyThread();
- MyThread(int count);
- void run();
- private:
- int count;
- };
- #endif // MYTHREAD_H
- //mythread.cpp
- #include "mythread.h"
- #include "QThread"
- #include <QDebug>
- MyThread::MyThread()
- {
- }
- MyThread::MyThread(int count)
- {
- this->count = count;
- }
- void MyThread::run()
- {
- while(count<20000)//為了檢視結果儘量設定大一些
- {
- qDebug()<< QThread::currentThread()->objectName()<<this->count++;
- }
- }
- //main.cpp
- #include <QtCore/QCoreApplication>
- #include "mythread.h"
- #include <QDebug>
- int main(int argc, char *argv[])
- {
- QCoreApplication a(argc, argv);
- qDebug()<< "Main Start";
- MyThread myThread1(0);
- myThread1.setObjectName("MyThread1");
- myThread1.start();
- MyThread myThread2(0);
- myThread2.setObjectName("MyThread2");
- myThread2.start();
- int c = 0;
- while(c < 20000)//為了檢視結果儘量設定大一些
- {
- qDebug()<< "Main Thread"<< c++;
- }
- return a.exec();
- }
在main函式中我定義了兩個執行緒,並分別設定了執行緒名稱。執行過程中有三個執行緒會可能同時執行。主函式執行緒,myThread1執行緒,myThread2執行緒。可以從執行結果看出:
g
Main Start
Main Thread 0
Main Thread 1
Main Thread 2
Main Thread 3
Main Thread 4
Main Thread 5
....
Main Thread 1040
Main Thread 1041
Main Thread 1042
Main Thread 1043
Main Thread 1044
"MyThread2" 0
"MyThread2" 1
"MyThread2" 2
"MyThread2" 3
"MyThread2" 4
"MyThread2" 5
"MyThread2" 6
.....
"MyThread2" 1158
"MyThread2" 1159
"MyThread2" 1160
"MyThread2" 1161
"MyThread2" 1162
"MyThread1" 0
"MyThread1" 1
"MyThread1" 2
"MyThread1" 3
"MyThread1" 4
"MyThread1" 5
.......
Main Thread 19990
Main Thread 19991
Main Thread 19992
Main Thread 19993
Main Thread 19994
Main Thread 19995
Main Thread 19996
Main Thread 19997
Main Thread 19998
Main Thread 19999
QThread包含一個列舉型別
enum Priority { IdlePriority, LowestPriority, LowPriority, NormalPriority, ..., InheritPriority } 這個列舉型別表示作業系統如何應安排新建立的執行緒
QThread::IdlePriority 0 安排只是CPU空閒時在執行
QThread::LowestPriority 1 安排最低優先順序
QThread::LowPriority 2 安排低優先順序
QThread::NormalPriority 3 安排正常優先順序
QThread::HighPriority 4 安排高優先順序
QThread::HighestPriority 5 安排高於最高.
QThread::TimeCriticalPriority 6 儘可能安排.
QThread::InheritPriority 7 安排使用繼承父類優先順序(預設)
公共方法:
QThread ( QObject * parent = 0 ) 建構函式,這個執行緒知道呼叫它的start函式時才會執行
~QThread () 解構函式
void exit ( int returnCode = 0 ) 呼叫此方法後,執行緒將退出事件迴圈並且返回從呼叫的QEventLoop::exec()的一個返回值
bool isFinished () const 返回執行緒是否已完成
bool isRunning () const 返回執行緒是否正在執行
Priority priority () const 返回執行緒的優先順序.如果執行緒沒有執行,將返回InheritPriority
void setPriority ( Priority priority ) 為正在執行的執行緒設定優先順序,如果執行緒未執行,將不做任何操作,立即返回.
void setStackSize ( uint stackSize ) 設定執行緒棧的大小的最大值,如果線上程中進行遞迴呼叫,那麼可以通過增加堆得大小來保證遞迴不會溢位。
uint stackSize () const 返回當前執行緒棧的最大值
bool wait ( unsigned long time = ULONG_MAX )阻塞執行緒直到執行緒結束執行或Time已經過去
槽:
void quit () 退出事件迴圈,等同於呼叫執行緒的exit(0),如果執行緒沒有事件迴圈則什麼也不做。
void start ( Priority priority = InheritPriority )開始執行執行緒
void terminate () 終止執行緒,執行緒是否立即被終止,依賴於作業系統.警告:這個函式是危險地,不被鼓勵使用
訊號:
void finished () 當執行緒結束執行時此訊號被髮射
void started () 當執行緒開始執行時此訊號被髮射
void terminated () 當執行緒被終止時此訊號被髮射
靜態成員:
QThread * currentThread () 返回指向當前執行緒的指標
Qt::HANDLE currentThreadId () 返回當前執行緒的控制代碼
int idealThreadCount () 返回當前作業系統能執行執行緒的數量
void yieldCurrentThread () 讓出CPU給其他執行緒,對於執行哪個執行緒完全決定於作業系統。
2、QRunnable
QRunable是所有可執行物件的基類。代表需要執行的一個任務或一段程式碼的介面。可以通過QThreadPool單獨執行執行緒。QThreadPool可以自動刪除QRunable如果此可執行物件的autoDelete()方法返回ture的話。我們可以使用setAutoDelete()函式設定auto-deletion標識.
總之QRunnable提供了簡潔有效的可執行物件的建立
優點: 建立過程簡潔, 使用方便, 配合著自身的autoDelete特性, 有點“招之即來, 揮之即去”的感覺.
缺點: 無法實時提供自身的執行狀態.
3、QThreadPool
執行緒池,用於管理一個執行緒的集和。
執行緒池用於管理和回收執行緒物件以減少程式中建立執行緒的花費。
每個Qt應用都有一個全域性的QThreadPool物件,通過QThreadPool::globalInstance()獲取
屬性:
activeThreadCount : const int 執行緒池中活動的執行緒個數
expiryTimeout : int 執行緒經過expiryTimeout未被使用將被認為expired並且exit。這種執行緒可以重新被restart.預設過期時間是30000毫秒即30秒。如果過期時間設定為負的,那麼被建立的執行緒將永遠不會exit直到執行緒池銷燬。設定過期時間不會影響到已經在執行的執行緒。只有新建立的執行緒使用這個過期時間。因此推薦在建立執行緒池後立即設定過期時間.
maxThreadCount : int 執行緒池中允許最大的執行緒數量。執行緒池最少允許一個執行緒,即使這個值被設定為0或負數.預設的最大執行緒數量是QThread::idealThreadCount()
公共方法:
QThreadPool ( QObject * parent = 0 )
~QThreadPool ()
int activeThreadCount () const 返回activeThreadCount屬性值
int expiryTimeout () const 返回expiryTimeout屬性值
int maxThreadCount () const 返回maxThreadCount屬性值
void releaseThread ()
void reserveThread () 儲存一個執行緒,
void setExpiryTimeout ( int expiryTimeout )
void setMaxThreadCount ( int maxThreadCount )
void start ( QRunnable * runnable, int priority = 0 ) 儲存一個執行緒並且執行可執行物件並且將可執行物件加入到執行佇列中,如果這個執行緒沒有使當前執行緒數超過最大執行緒數。
bool tryStart ( QRunnable * runnable ) 嘗試儲存一個執行緒並且執行可執行物件。如果沒有這時沒有時間片可以執行執行緒,那麼這個方法將什麼也不做。否則這個可執行物件執行緒將使用一個可執行執行緒立即執行。
void waitForDone () 等待所有執行緒退出,並且移除所有執行緒池中執行緒.
靜態函式
QThreadPool * QThreadPool::globalInstance () 獲取全域性執行緒物件
QThreadPool::globalInstance()->start(Runable例項);