QtConcurrent::run:高效並行編程實現方式

一、 QtConcurrent::run簡介

QtConcurrent是Qt框架中的一個模塊,旨在提供方便且高效的並行編程實現方式。其中QtConcurrent::run是使用最廣泛的方法。調用QtConcurrent::run時,將會自動將函數以一個新的線程運行,並將函數返回結果傳遞迴主線程。

QtConcurrent::run的用法簡單,僅需傳遞一個函數指針和函數參數,即可使用多線程的方式運行函數。使用QtConcurrent::run可以充分利用多核處理器,提高程序效率,同時避免了使用底層多線程時的一些容易出現的線程安全問題。

二、 使用QtConcurrent::run進行多線程編程

我們來看一個簡單的例子,假設我們需要對一個字符串進行加密處理:


QString encrypt(QString str, int key) {
    for(int i = 0; i < str.length(); ++i) {
        str[i] = str[i] ^ key;
    }
    return str;
}

接下來,我們通過QtConcurrent::run在新線程中運行這個函數:


QFuture future = QtConcurrent::run(encrypt, "hello world", 42);

使用QtConcurrent::run時,它不會佔用主線程的時間,而是會自動啟用一個新的線程去執行函數,這個新的線程會在後台運行,直到函數執行完畢並返回結果。

在這裡我們用QFuture保存異步操作的結果,QFuture表示未來的結果,這個結果可以在需要的時候被獲取。

下面,我們通過QFuture對象獲取異步操作的結果:


QString result = future.result();

在需要異步操作結果的地方使用future.result()來獲取異步操作結果,如果異步操作沒有完成,future.result()就會一直等待,直到異步操作完成為止。

三、使用QtConcurrent::run實現線程安全的容器操作

除了簡單的函數運算外,QtConcurrent::run還可以用於執行容器的並行操作,比如在多線程中對QList的修改操作。

在多線程中,對容器的修改操作需要考慮到線程安全,以避免出現競態條件等線程安全問題。一般的解決方法是添加互斥鎖,但互斥鎖會導致線程的等待與阻塞,降低程序的效率。

使用QtConcurrent::run可以方便地實現線程安全的容器操作,使用QtConcurrent::run時需要將需要並行執行的操作函數寫成可重入的函數。

以下是一個使用QtConcurrent::run實現並行容器操作的例子,這裡我們實現一個在多線程中並行地對一個QList進行排序的操作。


void sort(QList& list) {
    std::sort(list.begin(), list.end());
}

void parallelSort(QList& list) {
    QVector<QFuture> futures;
    const int threadCount = QThread::idealThreadCount();
    const int chunkSize = list.size() / threadCount;
    int begin = 0, end = chunkSize;
    for(int i = 0; i < threadCount; ++i) {
        if(i == threadCount - 1) {
            end = list.size();
        }
        futures.append(QtConcurrent::run(sort, list.mid(begin, end - begin)));
        begin = end;
        end += chunkSize;
    }
    for(int i = 0; i < futures.size(); ++i) {
        futures[i].waitForFinished();
    }
    std::inplace_merge(list.begin(), list.begin() + chunkSize, list.end());
}

parallelSort函數中,我們將要排序的QList按照QThread::idealThreadCount()的數量進行分割,並將每個子序列交給一個新線程去執行排序操作。

執行完所有子線程後,我們使用std::inplace_merge函數合併所有的排好序的子序列。

四、QtConcurrent::run的使用注意事項

雖然QtConcurrent::run提供了一種方便且高效的多線程編程實現方式,但其也有其適用的範圍和使用注意事項:

  1. 線程池內的線程更加傾向於長期存在,不要把耗時很短的任務放進線程池中,可能會導致線程池耗費過多的系統資源,不利於程序性能。
    
    // 不建議寫法
    for (int i = 0; i < 100; ++i) {
        QtConcurrent::run([](){ /* do something */ });
    }
    
  2. QtConcurrent::run會在新線程中自動執行函數,但也可以使用QThread手動地創建新線程。
    
    QThread* thread1 = new QThread();
    MyObject* object1 = new MyObject();
    object1->moveToThread(thread1);
    QObject::connect(thread1, &QThread::started, object1, &MyObject::mySlot);
    thread1->start();
    
  3. 使用QtConcurrent::run時需要注意線程安全,避免並發操作數據時出現競爭問題。
  4. QtConcurrent::run可以將函數的返回結果傳遞到主線程,但是如果異步操作返回的結果需要馬上使用,應使用QFuture::result()來等待異步操作的結束並獲取結果,否則可能會在異步操作沒結束前使用該結果。
    
    QString result = QtConcurrent::run(someFunction, params).result();
    

五、結語

QtConcurrent::run是Qt框架中提供的一種方便、高效的多線程編程實現方式。使用QtConcurrent::run可以避免使用底層多線程時的一些容易出現的線程安全問題,並充分利用多核處理器提高程序效率。

在使用QtConcurrent::run時需要注意線程安全,合理地使用QThread,避免將耗時很短的任務放進線程池中,正確地使用異步的結果等技巧,可以充分發揮QtConcurrent::run的優勢。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/244091.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-12 13:00
下一篇 2024-12-12 13:00

相關推薦

  • Python緩存圖片的處理方式

    本文將從多個方面詳細闡述Python緩存圖片的處理方式,包括緩存原理、緩存框架、緩存策略、緩存更新和緩存清除等方面。 一、緩存原理 緩存是一種提高應用程序性能的技術,在網絡應用中流…

    編程 2025-04-29
  • Trocket:打造高效可靠的遠程控制工具

    如何使用trocket打造高效可靠的遠程控制工具?本文將從以下幾個方面進行詳細的闡述。 一、安裝和使用trocket trocket是一個基於Python實現的遠程控制工具,使用時…

    編程 2025-04-28
  • Python在線編輯器的優勢與實現方式

    Python在線編輯器是Python語言愛好者的重要工具之一,它可以讓用戶方便快捷的在線編碼、調試和分享代碼,無需在本地安裝Python環境。本文將從多個方面對Python在線編輯…

    編程 2025-04-28
  • Python生成列表最高效的方法

    本文主要介紹在Python中生成列表最高效的方法,涉及到列表生成式、range函數、map函數以及ITertools模塊等多種方法。 一、列表生成式 列表生成式是Python中最常…

    編程 2025-04-28
  • Java表單提交方式

    Java表單提交有兩種方式,分別是get和post。下面我們將從以下幾個方面詳細闡述這兩種方式。 一、get方式 1、什麼是get方式 在get方式下,表單的數據會以查詢字符串的形…

    編程 2025-04-27
  • TFN MR56:高效可靠的網絡環境管理工具

    本文將從多個方面深入闡述TFN MR56的作用、特點、使用方法以及優點,為讀者全面介紹這一高效可靠的網絡環境管理工具。 一、簡介 TFN MR56是一款多功能的網絡環境管理工具,可…

    編程 2025-04-27
  • 用Pythonic的方式編寫高效代碼

    Pythonic是一種編程哲學,它強調Python編程風格的簡單、清晰、優雅和明確。Python應該描述為一種語言而不是一種編程語言。Pythonic的編程方式不僅可以使我們在編碼…

    編程 2025-04-27
  • Java多版本支持實現方式

    本文將從以下幾個方面闡述如何實現Java多版本支持,並給出可行的代碼示例。 一、多版本Java環境概述 Java是一門跨平台的編程語言,但是在不同的應用場景下,可能需要使用不同版本…

    編程 2025-04-27
  • SpringBoot Get方式請求傳參用法介紹

    本文將從以下多個方面對SpringBoot Get方式請求傳參做詳細的闡述,包括URL傳參、路徑傳參、請求頭傳參、請求體傳參等,幫助讀者更加深入地了解Get請求方式下傳參的相關知識…

    編程 2025-04-27
  • Python生成10萬條數據的高效方法

    本文將從以下幾個方面探討如何高效地生成Python中的10萬條數據: 一、使用Python內置函數生成數據 Python提供了許多內置函數可以用來生成數據,例如range()函數可…

    編程 2025-04-27

發表回復

登錄後才能評論