QtConcurrent应用解析

目录

对比传统线程

1. QtConcurrent::run() —— 异步运行函数

2.QtConcurrent::mapped() —— 并行转换

3. QtConcurrent::filter() —— 并行过滤

4. QtConcurrent::run() + QFutureWatcher —— UI 异步更新

5.线程池配置

QtConcurrent 是 Qt 框架提供的一个 高级并发编程模块,它封装了多线程操作,使得开发者可以在 不直接接触低级线程原语(如 QThread、互斥锁等) 的前提下,轻松实现并行计算。它基于 线程池(QThreadPool)模板函数,支持异步执行任务、并行算法(如 map、filter、reduce)等

对比传统线程

特性QThreadQtConcurrent
抽象层级低(需管理线程生命周期)高(自动线程池管理)
代码复杂度高(需继承/重写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);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/96359.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/96359.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大疆图传十公里原理:无人机图传技术解析

大疆图传系统的核心在于把发射端的能量、机载接收的灵敏度、以及环境中的衰减因素&#xff0c;进行科学的预算与动态的修正。简单的说&#xff0c;就是通过精准的链路预算来确保在最坏环境下仍有可用的信号空间。发射功率、天线增益、空中与地面的路径损耗、接收端的噪声底线等…

jmeter 带函数压测脚本

包含时间戳获取、md5值计算、随机字符串获取<?xml version"1.0" encoding"UTF-8"?> <jmeterTestPlan version"1.2" properties"5.0" jmeter"5.6.3"><hashTree><TestPlan guiclass"TestPlanGui&…

鸿蒙app日志存储

app的pid获取 import process from @ohos.process;@Entry @Component struct MainAbility {aboutToAppear(): void {console.log(this.TAG,"pid: "+process.pid)}} 获取本应用日志 在Android中可以使用logcat --pid xxxx 获取特定进程xxxx的打印日志 在鸿蒙中也有…

02.【Linux系统编程】Linux权限(root超级用户和普通用户、创建普通用户、sudo短暂提权、权限概念、权限修改、粘滞位)

目录 1. root超级用户和普通用户 2. 创建普通用户、密码设置、切换用户 3. sudo短暂提权&#xff08;给普通用户添加sudo权限&#xff09; 4. 权限 4.1 是什么 4.2 为什么有权限&#xff1f;&#xff08;权限 角色 目标属性&#xff09; 4.2.1 角色 4.2.2 目标属性 …

阿里云可观测 2025 年 8 月产品动态

本月可观测热文回顾 文章一览&#xff1a; 零代码改造&#xff01;LoongSuite AI 采集套件观测实战 性能瓶颈定位更快更准&#xff1a;ARMS 持续剖析能力升级解析 不只是告警&#xff1a;用阿里云可观测 MCP 实现 AK 高效安全审计 金蝶云•星辰基于 SLS 构建稳定高效可观测…

绿虫零碳助手:通过电费推算用电量,确认光伏装机规模

在光伏项目开发前期&#xff0c;精准掌握用电需求与合理确定装机规模是关键环节。前者决定光伏系统需满足的用电基数&#xff0c;后者影响项目投资成本与发电收益匹配度。通过电费数据推算实际用电量&#xff0c;再结合专业工具计算光伏装机参数&#xff0c;可有效降低项目规划…

融智学:构建AI时代学术的新范式

融智学&#xff1a;构建AI时代学术新范式摘要&#xff1a;邹晓辉提出的融智学为现代学术体系困境提供系统性解决方案&#xff0c;通过"问题与价值驱动"的新范式取代传统"发表驱动"模式。该体系包含三大核心&#xff1a;哲学基础&#xff08;唯文主义、信息…

【JavaEE初阶】-- JVM

文章目录1. JVM运行流程2. Java运行时数据区2.1 方法区&#xff08;内存共享&#xff09;2.2 堆&#xff08;内存共享&#xff09;2.3 Java虚拟机栈&#xff08;线程私有&#xff09;2.4 本地方法栈&#xff08;线程私有&#xff09;2.5 程序计数器&#xff08;线程私有&#x…

第十四届蓝桥杯青少组C++选拔赛[2023.1.15]第二部分编程题(4 、移动石子)

参考程序1&#xff1a;#include <bits/stdc.h> using namespace std; int main() {int N;cin >> N;vector<int> stones(N);int sum 0;for (int i 0; i < N; i) {cin >> stones[i];sum stones[i];}int target sum / N; // 每个篮子的平均值int a…

Spring Boot 的注解是如何生效的

在 Spring 中&#xff0c;Configuration、ComponentScan、Bean、Import 等注解的扫描、解析和 BeanDefinition 注册是一个分层处理的过程。下面我们以 Configuration 类为例&#xff0c;结合代码流程详细说明其从扫描到注册的完整逻辑。 1. 整体流程概览 以下是核心步骤的流程图…

Django REST Framework响应类Response详解

概述 Response 类是一个智能的 HTTP 响应类&#xff0c;能够根据客户端请求的内容类型&#xff08;Content-Type&#xff09;自动将数据渲染成合适的格式&#xff08;JSON、XML、HTML等&#xff09;。 基本用法 from rest_framework.response import Response# 最简单的用法 de…

# 小程序 Web 登录流程完整解析

登录流程完整小白解析&#xff08;小程序 & Web&#xff09; 在开发中&#xff0c;登录是每个系统最基础的功能。为了让小白也能理解&#xff0c;我们用通俗类比和流程讲解 小程序登录、Web 登录、Token 刷新、安全存储等整个过程。1️⃣ 小程序登录流程&#xff08;小白理…

安装vcenter6.7 第二阶段安装很慢 或卡在50%

DNS、FQDN配置的问题采用VCSA安装vCenter时&#xff0c;第一步安装还算顺利&#xff0c;第二步就会安装失败&#xff0c;而且还特别慢&#xff0c;这是因为部署时需要DNS服务器&#xff0c;下面就是不采用DNS服务器的部署方案。第一步&#xff1a;正常安装&#xff0c;DNS就写本…

第十六届蓝桥杯软件赛 C 组省赛 C++ 题解

大家好&#xff0c;今天是 2025 年 9 月 11 日&#xff0c;我来给大家写一篇关于第十六届蓝桥杯软件赛 C 组省赛的C 题解&#xff0c;希望对大家有所帮助&#xff01;&#xff01;&#xff01; 创作不易&#xff0c;别忘了一键三连 题目一&#xff1a;数位倍数 题目链接&…

项目帮助文档的实现

项目帮助文档的实现 代码如下&#xff1a; #ifndef __M_HELPER_H__ #define __M_HELPER_H__ #include <iostream> #include <fstream> #include <string> #include <vector> #include <sqlite3.h> #include <random> #include <sstream…

python逆向-逆向pyinstaller打包的exe程序反编译获取源代码

python逆向-逆向pyinstaller打包的exe程序反编译获取源代码 Pyinstaller pyinstaller 是一个用于将 Python 程序打包成独立可执行文件的工具&#xff0c;能够在没有 Python 解释器的情况下运行。 Python 脚本转换为 Windows、macOS 和 Linux 操作系统上的可执行文件。 把Python…

【SQL】-- sql having 和 where 的 区别

HAVING 和 WHERE 都是用来筛选数据的&#xff0c;但它们的应用场景有所不同。WHERE&#xff1a;用于筛选行数据&#xff0c;通常在 FROM 子句之后执行。它在分组操作 (GROUP BY) 之前应用&#xff0c;用来筛选出符合条件的记录。示例&#xff1a;SELECT name, age FROM employe…

MySQL,SQL Server,PostgreSQL三种数据库各自的优缺点,分别适用哪些场景

MySQL的优缺点及适用场景优点开源免费&#xff0c;社区版可商用&#xff0c;成本低。轻量级&#xff0c;安装配置简单&#xff0c;适合中小型项目。读写性能优异&#xff0c;尤其在OLTP&#xff08;在线事务处理&#xff09;场景下表现突出。支持主从复制、分片等扩展方案&…

Java 类加载机制双亲委派与自定义类加载器

我们来深入解析 Java 类加载机制。这是理解 Java 应用如何运行、如何实现插件化、以及解决一些依赖冲突问题的关键。一、核心概念&#xff1a;类加载过程一个类型&#xff08;包括类和接口&#xff09;从被加载到虚拟机内存开始&#xff0c;到卸载出内存为止&#xff0c;它的整…

Kaggle项目实践——Titanic: Machine Learning from Disaster

泰坦尼克号沉船事件是机器学习领域最经典的入门项目之一。Kaggle 上的 Titanic: Machine Learning from Disaster 竞赛&#xff0c;被无数人称为“机器学习的 Hello World”。 一、数据导入与清洗&#xff1a;让数据从 “杂乱” 变 “干净” 机器学习模型就像 “挑食的孩子”…