轉載豆子 Qt 學習之路 2(73):Qt 線程相關類

希望上一章有關事件循環的內容還沒有把你繞暈。本章將重新回到有關線程的相關內容上面來。在前面的章節我們瞭解了有關QThread類的簡單使用。不過,Qt 提供的有關線程的類可不那麼簡單,否則的話我們也沒必要再三強調使用線程一定要萬分小心,一不留神就會陷入陷阱。

事實上,Qt 對線程的支持可以追溯到2000年9月22日發佈的 Qt 2.2。在這個版本中,Qt 引入了QThread。不過,當時對線程的支持並不是默認開啓的。Qt 4.0 開始,線程成爲所有平臺的默認開啓選項(這意味着如果不需要線程,你可以通過編譯選項關閉它,不過這不是我們現在的重點)。現在版本的 Qt 引入了很多類來支持線程,下面我們將開始逐一瞭解它們。

QThread是我們將要詳細介紹的第一個類。它也是 Qt 線程類中最核心的底層類。由於 Qt 的跨平臺特性,QThread要隱藏掉所有平臺相關的代碼。

正如前面所說,要使用QThread開始一個線程,我們可以創建它的一個子類,然後覆蓋其QThread::run()函數:

class Thread : public QThread
{
protected:
    void run()
    {
        /* 線程的相關代碼 */
    }
};

然後我們這樣使用新建的類來開始一個新的線程:

Thread *thread = new Thread;
thread->start(); // 使用 start() 開始新的線程

注意,從 Qt 4.4 開始,QThread就已經不是抽象類了。QThread::run()不再是純虛函數,而是有了一個默認的實現。這個默認實現其實是簡單地調用了QThread::exec()函數,而這個函數,按照我們前面所說的,其實是開始了一個事件循環(有關這種實現的進一步闡述,我們將在後面的章節詳細介紹)。

QRunnable是我們要介紹的第二個類。這是一個輕量級的抽象類,用於開始一個另外線程的任務。這種任務是運行過後就丟棄的。由於這個類是抽象類,我們需要繼承QRunnable,然後重寫其純虛函數QRunnable::run()

class Task : public QRunnable
{
public:
    void run()
    {
        /* 線程的相關代碼 */
    }
};

要真正執行一個QRunnable對象,我們需要使用QThreadPool類。顧名思義,這個類用於管理一個線程池。通過調用QThreadPool::start(runnable)函數,我們將一個QRunnable對象放入QThreadPool的執行隊列。一旦有線程可用,線程池將會選擇一個QRunnable對象,然後在那個線程開始執行。所有 Qt 應用程序都有一個全局線程池,我們可以使用QThreadPool::globalInstance()獲得這個全局線程池;與此同時,我們也可以自己創建私有的線程池,並進行手動管理。

需要注意的是,QRunnable不是一個QObject,因此也就沒有內建的與其它組件交互的機制。爲了與其它組件進行交互,你必須自己編寫低級線程原語,例如使用 mutex 守護來獲取結果等。

QtConcurrent是我們要介紹的最後一個對象。這是一個高級 API,構建於QThreadPool之上,用於處理大多數通用的並行計算模式:map、reduce 以及 filter。它還提供了QtConcurrent::run()函數,用於在另外的線程運行一個函數。注意,QtConcurrent是一個命名空間而不是一個類,因此其中的所有函數都是命名空間內的全局函數。

不同於QThreadQRunnableQtConcurrent不要求我們使用低級同步原語:所有的QtConcurrent都返回一個QFuture對象。這個對象可以用來查詢當前的運算狀態(也就是任務的進度),可以用來暫停/回覆/取消任務,當然也可以用來獲得運算結果。注意,並不是所有的QFuture對象都支持暫停或取消的操作。比如,由QtConcurrent::run()返回的QFuture對象不能取消,但是由QtConcurrent::mappedReduced()返回的是可以的。QFutureWatcher類則用來監視QFuture的進度,我們可以用信號槽與QFutureWatcher進行交互(注意,QFuture也沒有繼承QObject)。

下面我們可以對比一下上面介紹過的三種類:

特性 QThread QRunnable QtConcurrent
高級 API
面向任務
內建對暫停/恢復/取消的支持
具有優先級
可運行事件循環
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章