目录
对比传统线程
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);