目錄
對比傳統線程
1.?QtConcurrent::run()?—— 異步運行函數
2.QtConcurrent::mapped()?—— 并行轉換
3.?QtConcurrent::filter()?—— 并行過濾
4.?QtConcurrent::run()?+?QFutureWatcher?—— UI 異步更新
5.線程池配置
QtConcurrent 是 Qt 框架提供的一個 高級并發編程模塊,它封裝了多線程操作,使得開發者可以在 不直接接觸低級線程原語(如 QThread、互斥鎖等) 的前提下,輕松實現并行計算。它基于 線程池(QThreadPool) 和 模板函數,支持異步執行任務、并行算法(如 map、filter、reduce)等
對比傳統線程
特性 | QThread | QtConcurrent |
---|---|---|
抽象層級 | 低(需管理線程生命周期) | 高(自動線程池管理) |
代碼復雜度 | 高(需繼承/重寫run) | 低(函數式編程) |
適用場景 | 長期后臺任務 | 短期并行數據處理 |
通過 QtConcurrent 可顯著減少并發代碼量,典型性能提升場景包括:大數據集轉換(提速 3-8 倍,取決于 CPU 核心數)、批量文件處理等。建議結合?
QFutureWatcher
?實現進度反饋,提升用戶體驗。| 模塊 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | 作用 ? ? ? ? ? ? ? ? ? ? ? ?|
| ---------------------------------------- | ------------------------- |
| `QtConcurrent::run()` ? ? ? ? ? ? ? ? ? ?| 在后臺線程中異步運行函數 ? ? ? ? ? ? ?|
| `QtConcurrent::map()` ? ? ? ? ? ? ? ? ? ?| 對容器中的每個元素并行應用函數 ? ? ? ? ? |
| `QtConcurrent::mapped()` ? ? ? ? ? ? ? ? | 并行轉換容器,返回新容器 ? ? ? ? ? ? ?|
| `QtConcurrent::filter()` ? ? ? ? ? ? ? ? | 并行過濾容器元素 ? ? ? ? ? ? ? ? ?|
| `QtConcurrent::filtered()` ? ? ? ? ? ? ? | 并行過濾并返回新容器 ? ? ? ? ? ? ? ?|
| `QtConcurrent::run()` + `QFutureWatcher` | 實現異步任務 + UI 通知 ? ? ? ? ? ?|
| `QFuture<T>` ? ? ? ? ? ? ? ? ? ? ? ? ? ? | 表示異步計算的結果 ? ? ? ? ? ? ? ? |
| `QFutureWatcher<T>` ? ? ? ? ? ? ? ? ? ? ?| 監聽 QFuture 的完成信號,用于 UI 更新 |
1.?QtConcurrent::run()
?—— 異步運行函數
auto future = QtConcurrent::run([]() {// 耗時操作return 42;
});
int result = future.result(); // 阻塞等待結果
-
支持普通函數、lambda、成員函數。
-
返回
QFuture<T>
,可用QFutureWatcher
監聽完成。
2.QtConcurrent::mapped()
?—— 并行轉換
QList<int> input = {1, 2, 3, 4};
auto future = QtConcurrent::mapped(input, [](int val) {return val * val;
});
QList<int> result = future.results(); // {1, 4, 9, 16}
-
不修改原容器,返回新容器。
-
自動并行處理,線程數由 QThreadPool 控制。
3.?QtConcurrent::filter()
?—— 并行過濾
QList<int> input = {1, 2, 3, 4, 5};
auto future = QtConcurrent::filtered(input, [](int val) {return val % 2 == 0;
});
QList<int> result = future.results(); // {2, 4}
4.?QtConcurrent::run()
?+?QFutureWatcher
?—— UI 異步更新
QFutureWatcher<int> *watcher = new QFutureWatcher<int>(this);
connect(watcher, &QFutureWatcher<int>::finished, this, [watcher]() {int result = watcher->result();qDebug() << "Result:" << result;
});QFuture<int> future = QtConcurrent::run([]() {QThread::sleep(2);return 42;
});
watcher->setFuture(future);
5.線程池配置
QtConcurrent 默認使用全局線程池
#include <QApplication>
#include <QPlainTextEdit>
#include <QFutureWatcher>
#include <QtConcurrent>
#include <QThread>
#include <QThreadPool>
#include <QVBoxLayout>
#include <QPushButton>
#include <QDateTime>/* 模擬耗時任務:把輸入字符串重復 n 次,中間 sleep 模擬 1 s 工作量 */
static QString heavyWork(const QString &in, int n)
{QString out;for (int i = 0; i < n; ++i) {out += in + ' ';QThread::msleep(200); // 讓任務跑慢點,方便觀察并發}// 打印當前線程 ID,驗證線程池復用qDebug() << "[heavyWork]" << in << "thread =" << QThread::currentThread();return out.trimmed();
}class Demo : public QWidget
{Q_OBJECT
public:Demo(QWidget *parent = nullptr) : QWidget(parent){setWindowTitle("QtConcurrent 默認全局線程池示例");auto *lay = new QVBoxLayout(this);btn.setText("開始 3 個并發任務");lay->addWidget(&btn);log.setReadOnly(true);lay->addWidget(&log);/* 1. 修改全局線程池容量(僅用于演示) */QThreadPool::globalInstance()->setMaxThreadCount(2);log.appendPlainText(QString("全局線程池 maxThreadCount = %1").arg(QThreadPool::globalInstance()->maxThreadCount()));connect(&btn, &QPushButton::clicked, this, &Demo::startTasks);}private slots:void startTasks(){btn.setEnabled(false);log.appendPlainText("--- 任務已提交 ---");/* 2. 提交 3 個任務,全部進入**同一個**全局線程池 */for (int i = 0; i < 3; ++i) {auto *watcher = new QFutureWatcher<QString>(this);/* 任務完成后把結果打印到日志 */connect(watcher, &QFutureWatcher<QString>::finished,this, [this, watcher]() {log.appendPlainText(QString("[finished] %1").arg(watcher->result()));watcher->deleteLater();});/* 3. 使用 QtConcurrent::run() —— 不指定線程池,即走全局線程池 */QFuture<QString> future =QtConcurrent::run(heavyWork, QString("Task%1").arg(i + 1), 5);watcher->setFuture(future);}log.appendPlainText("(所有任務已提交,線程池自動調度)");}private:QPushButton btn;QPlainTextEdit log;
};#include "main.moc"int main(int argc, char *argv[])
{QApplication a(argc, argv);Demo w;w.resize(500, 350);w.show();return a.exec();
}/*
全局線程池 maxThreadCount = 2
--- 任務已提交 ---
(所有任務已提交,線程池自動調度)
[heavyWork] "Task1" thread = QThread(0x1e4e9f0, name = "Thread (pooled)")
[heavyWork] "Task2" thread = QThread(0x1e4ea90, name = "Thread (pooled)")
[heavyWork] "Task3" thread = QThread(0x1e4e9f0, name = "Thread (pooled)")
[finished] "Task1 Task1 Task1 Task1 Task1"
[finished] "Task2 Task2 Task2 Task2 Task2"
[finished] "Task3 Task3 Task3 Task3 Task3"
*/
實例:并行計算圖片縮略圖
QList<QString> imagePaths = ...;
auto future = QtConcurrent::mapped(imagePaths, [](const QString &path) {QImage image(path);return image.scaled(128, 128);
});QFutureWatcher<QImage> *watcher = new QFutureWatcher<QImage>(this);
connect(watcher, &QFutureWatcher<QImage>::resultReadyAt, this, [watcher](int index) {QImage thumb = watcher->resultAt(index);// 顯示縮略圖
});
watcher->setFuture(future);