Qt 多线程之QtConcurrent::map(处理序列容器)

news2024/12/26 21:22:49

QtConcurrent::map()、QtConcurrent::mapped() 和 QtConcurrent::mappedReduced() 函数对一个序列中(例如:QList、QVector)的项目并行地进行计算。

1、map函数

map函数的功能是在其他线程运行指定的函数,map函数有两个参数

第一个是集合

第二个参数是一个函数。它的作用就是同时用第二个参数来计算第一个参数中的每一个元素,且结果直接覆盖到元素中,如果是成员函数,那要静态成员函数才能运行

 1 //静态函数
 2 void Widget::Func(QPushButton * & btn)
 3 {
 4     QTime time = QTime::currentTime();
 5     qsrand(time.msec() + time.second()*1000);
 6     btn->setText(QString("按钮_%1").arg(qrand() % 20));
 7     qDebug()<<"thread ID"<<QThread::currentThreadId();
 8 }
 9  
10 void Widget::on_pushButton_clicked()
11 {
12     QList<QPushButton*> list = this->findChildren<QPushButton*>();
13     QFuture<void> f = QtConcurrent::map(list,&Widget::Func); //map函数 不能运行非静态成员函数
14     f.waitForFinished();
15 }

结果:

 

2、mapped函数

mapped函数的作用和map类似,只是把计算结果放到了新的容器中

例子1:

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QT嵌入式开发,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

 1 int func2(int a)
 2 {
 3     return a + 1;
 4 }
 5  
 6 void Widget::on_pushButton_clicked()
 7 {
 8     QList<int> alist;
 9     alist<<1<<3<<5<<7<<9;
10  
11     QFuture<int> f = QtConcurrent::mapped(alist,func2); //QFuture的类型为int
12     f.waitForFinished();
13     qDebug()<<"alist"<<alist;
14     QList<int> newlist = f.results();
15     qDebug()<<"newlist"<<newlist;
16 }

结果:

 

例子2:

 1 QPushButton* Widget::Func2(QPushButton * btn)
 2 {
 3     QThread::msleep(200);
 4     QTime time = QTime::currentTime();
 5     qsrand(time.msec() + time.second()*1000);
 6     btn->setText(QString("按钮_%1").arg(qrand() % 20));
 7     qDebug()<<"thread ID"<<QThread::currentThreadId();
 8     return btn;
 9 }
10  
11 void Widget::on_pushButton_clicked()
12 {
13     QList<QPushButton*> list = this->findChildren<QPushButton*>();
14     QFuture<QPushButton*> f2 = QtConcurrent::mapped(list,&Widget::Func2);
15     f2.waitForFinished();
16 }

结果:

 

关于mapped,官方有个:Image Scaling Example例子,通过一次性加载多张图片,分别转成100*100的缩略图显示在界面来演示mapped的使用。

 1 //图片转换成100*100的图片
 2 QImage scale(const QString &imageFileName)
 3 {
 4     QImage image(imageFileName);
 5     QThread::msleep(500);
 6     return image.scaled(QSize(imageSize, imageSize), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
 7 }
 8  
 9 QFutureWatcher imageScaling = new QFutureWatcher<QImage>(this);
10 connect(imageScaling, &QFutureWatcherBase::resultReadyAt, this, &Images::showImage);
11 connect(imageScaling, &QFutureWatcherBase::finished, this, &Images::finished);
12  
13 QStringList files;//图片地址
14 imageScaling->setFuture(QtConcurrent::mapped(files, scale));
15  
16 connect(pauseButton, &QAbstractButton::clicked, imageScaling, &QFutureWatcherBase::togglePaused);//暂停/恢复操作

QFutureWatcherBase::togglePaused 暂停/继续操作

QFutureWatcherBase::resultReadyAt 读取到一个结果

可以用这些信号来设置处理的进度条

用这些信号设置进度条官方正好有个叫:QtConcurrent Progress Dialog Example的简单例子:

 1 void spin(int &iteration)
 2 {
 3     volatile int v = 0;
 4     for (int j = 0; j < 400000000; ++j)
 5         ++v;
 6     qDebug() << "处理值" << iteration << "的线程:" << QThread::currentThreadId();
 7 }
 8  
 9 int main(int argc, char **argv)
10 {
11     QApplication app(argc, argv);
12  
13     QVector<int> vector;
14     for (int i = 0; i < 20; ++i)
15         vector.append(i);
16  
17     QProgressDialog dialog;
18     dialog.setLabelText(QString("正在使用 %1 个线程...").arg(QThread::idealThreadCount()));
19  
20     QFutureWatcher<void> futureWatcher;
21     QObject::connect(&futureWatcher, &QFutureWatcherBase::finished, &dialog, &QProgressDialog::reset);
22     QObject::connect(&dialog, &QProgressDialog::canceled, &futureWatcher, &QFutureWatcherBase::cancel);
23     QObject::connect(&futureWatcher, &QFutureWatcherBase::progressRangeChanged, &dialog, &QProgressDialog::setRange);
24     QObject::connect(&futureWatcher, &QFutureWatcherBase::progressValueChanged, &dialog, &QProgressDialog::setValue);
25  
26     futureWatcher.setFuture(QtConcurrent::map(vector, spin));
27     dialog.exec();
28     futureWatcher.waitForFinished();
29     qDebug() << "Canceled?" << futureWatcher.future().isCanceled();
30 }

3、mappedReduced函数

mappedReduced函数比mapped多一个参数,这个参数也是个函数。作用就是将mapped出来的结果再计算最终得出一个值。

 1 int func3(int a)
 2 {
 3     return a + 1;
 4 }
 5  
 6 void sum(int& result, const int& b)
 7 {
 8     result += b;
 9 }
10  
11 void Widget::on_pushButton_clicked()
12 {
13     QList<int> alist;
14     alist<<1<<3<<5<<7<<9;
15  
16     QFuture<int> result = QtConcurrent::mappedReduced(alist,func3,sum);
17     result.waitForFinished();
18     qDebug()<<result.result();
19 }

alist中的一个值执行完func3马上执行sum,而不是alist中所有之都执行完才执行sum。

结果:

关于mappedReduced,官方的demo中有个叫做QtConcurrent Word Count Example的例子通过单线程/多线程统计文件夹中单词个数来演示mappedReduced的使用。

 1 //遍历文件夹,返回文件夹内所有文件名
 2 QStringList findFiles(const QString &startDir, QStringList filters)
 3 {
 4     QStringList names;
 5     QDir dir(startDir);
 6  
 7     foreach (QString file, dir.entryList(filters, QDir::Files))
 8         names += startDir + "/" + file;
 9  
10     foreach (QString subdir, dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot))
11         names += findFiles(startDir + "/" + subdir, filters);
12     return names;
13 }
14  
15 //单线程计算此文件列表中每个文件的单词个数:<文件名,单词个数>
16 QMap<QString, int> singleThreadedWordCount(QStringList & files)
17 {
18     QMap<QString, int> wordCount;
19     QString word;
20     foreach (QString file, files)
21     {
22         QFile f(file);
23         f.open(QIODevice::ReadOnly);
24         QTextStream textStream(&f);
25         while (textStream.atEnd() == false)
26             foreach(word, textStream.readLine().split(" "))
27                 wordCount[word] += 1;
28     }
29     return wordCount;
30 }
31  
32 //计算一个文件中单词数
33 QMap<QString, int> countWords(const QString &file)
34 {
35     QFile f(file);
36     f.open(QIODevice::ReadOnly);
37     QTextStream textStream(&f);
38     QMap<QString, int> wordCount;
39  
40     while (textStream.atEnd() == false)
41         foreach (QString word, textStream.readLine().split(" "))
42             wordCount[word] += 1;
43  
44     return wordCount;
45 }
46  
47 void reduce(QMap<QString, int> &result, const QMap<QString, int> &w)
48 {
49     QMapIterator<QString, int> it(w);
50     while (it.hasNext())
51     {
52         it.next();
53         result[it.key()] += it.value();
54     }
55 }
 1 int main(int argc, char** argv)
 2 {
 3     QApplication app(argc, argv);
 4     qDebug() << "正在查找文件...";
 5     QStringList files = findFiles("../../",
 6                                   QStringList() << "*.cpp" << "*.h");//查找此格式的文件
 7     QTime time;
 8     time.start();
 9     QMap<QString, int> total = singleThreadedWordCount(files);
10  
11     int singleThreadTime = 0;
12     {
13         QTime time;
14         time.start();
15         QMap<QString, int> total = singleThreadedWordCount(files);
16         singleThreadTime = time.elapsed();
17         qDebug() << "单线程统计这些文件单词数所需时间:" << singleThreadTime;
18     }
19  
20     int mapReduceTime = 0;
21     {
22         QTime time;
23         time.start();
24         QMap<QString, int> total = mappedReduced(files, countWords, reduce);
25         mapReduceTime = time.elapsed();
26         qDebug() << "MapReduce" << mapReduceTime;
27     }
28     qDebug() << "速度提升倍数:" << ((double)singleThreadTime - (double)mapReduceTime) / (double)mapReduceTime + 1;
29 }
QMap<QString, int> total = mappedReduced(files, countWords, reduce);

这句在多线程里对文件列表中的每个文件执行统计单词操作(执行countWords),然后把统计结果存到QMap中(执行reduce)

打印reduce()中的result的地址可以发现result一直是同一个,猜测:这个QMap<QString, int> &result是mappedReduced申请的,执行reduce时候把数据都保存到这个result里,执行完mappedReduced了就返回值

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QT嵌入式开发,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

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

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

相关文章

耗时一个月整理的,最新出炉的Java面试题合集(2022亲身经历)

面试题清单 个人近来面试了不少的公司的&#xff0c;该挂的挂&#xff0c;该应付通过的应付通过&#xff0c;目前对面试题部分做一个系统的总结。最起码要保证被问过的问题第二次被问到的时候是可以回答并且理解的。算是一个被动输入学习的过程。 题目持续更新&#xff0c;答…

xdma linux 驱动

一、下载XDMA文件 输入命令: sudo git clone https://github.com/Xilinx/dma_ip_drivers cd xx_dma/dma_ip_drivers/XDMA/linux-kernel/xdma$ 二 、编译: sudo make install 在最后会遇到下面这个问题: 三、添加key 文件 cd /lib/modules/5.4.0-135-generic/build/ce…

使用 EF Core 处理Sqlite数据库

使用 EF Core 处理Sqlite数据库 1.通过NuGet安装Microsoft.EntityFrameworkCore.Sqlite 2.编写生成数据库的实体类 因为EF Core是通过实体类来作为数据库的字段 public class User {/// <summary>/// 主键 Id/// </summary>[Key]public int Id { get; set; }///…

代码上传gitee

有两种场景&#xff1a; 一、自己的代码没有用git管理&#xff0c;先将自己的代码用git管理起来&#xff0c;然后上传gitee gitee注册账号后&#xff0c;点“”号创建代码仓库&#xff0c;这就是你的代码库上传后的路径。 然后填写仓库名称和路径&#xff0c;这个可以随便写&…

【论文合集】2022年10月医学影像期刊论文合集

★ 本月IEEE Transactions on Medical Imaging(1区 top if 11.037) 共32篇, Medical Image Analysis&#xff08;1区 top if 13.828&#xff09; 共30篇. ”标题高频词汇 (segmentation, 13), (brain, 9), (mri, 6), (graph, 4)(attention, 4), (3d, 4), (contrastive, 4), …

代理模式--【学习笔记】

什么是代理模式&#xff1f; 代理是一种模式,提供了对目标对象的间接访问方式,即通过代理对象访问目标对象.如此便于在目标实现的基础上增加额外的功能操作,以满足自身的业务需求. 代理模式又分为静态代理&#xff0c;动态代理 静态代理模式 编写代理类, 要求: 代理类与目标类…

【我爱世界杯】伪球迷眼里的世界杯

大家好&#xff0c;我是【架构师李肯】&#xff0c;一个专注于嵌入式物联网架构设计的攻城狮。 文章目录按理说聊一聊我和足球第一次热衷于关注世界杯后ying情时代的卡塔尔世界杯祝愿世界杯按理说 嗯&#xff0c;按理说&#xff0c;我一个程序猿&#xff0c;既不踢球&#xff…

ChatGPT原理解析-张俊林

本文将从以下几个方面展开&#xff1a; 引言 ChatGPT的技术原理 引言 作为智能对话系统&#xff0c;ChatGPT最近两天爆火&#xff0c;都火出技术圈了&#xff0c;网上到处都在转ChatGPT相关的内容和测试例子&#xff0c;效果确实很震撼。我记得上一次能引起如此轰动的AI技术…

湃睿PMDS-Fx传感器在电动牙刷上的应用

电动牙刷、冲牙器等产品市场的爆发性增长&#xff0c;显示全球人口正在越来越关注牙齿/口腔的健康问题。 根据资料显示&#xff0c;中国电动牙刷市场规模呈现逐年上涨的态势&#xff0c;2017年中国电动牙刷市场规模为43亿元&#xff0c;2021年中国电动牙刷市场规模上涨为125亿…

01-go基础-10-结构体 struct (定义结构体、声明结构体变量、结构体赋值、结构体做参数、结构体指针、结构体嵌套、结构体打印)

文章目录1. 定义结构体类型2. 声明结构体变量3. 赋值3.1 用结构体赋值3.2 每个成员分别赋值4. 结构体使用4.1 结构体作参数4.2 结构体指针做参数4.3 二者区别4.4 本质原因5. 结构体嵌套5.1 一个结构体作为另一个结构体的成员1&#xff09;定义2&#xff09;赋值和引用3&#xf…

RabbitMQ的学习

MQ引言 什么是MQ MQ(Message Quene)&#xff1a;翻译为消息队列&#xff0c;通过典型的生产者和消费者模型生产者不断向消息队列中生产消息&#xff0c;消费者不断的从队列中获取消息。因为消息的生产和消费都是异步的&#xff0c;而且只关心消息的发送和接收&#xff0c;没有…

【MySQL 原理篇】- 凭这个,我拿下字节面试

若是想查看原图&#xff0c;请点击这里 刘卡卡 | ProcessOn 超链接 索引 从存储结构上看&#xff0c;有哪些索引从存储结构上来划分&#xff1a;BTree索引&#xff08;B-Tree或BTree索引&#xff09;&#xff0c;Hash索引&#xff0c;full-index全文索引&#xff0c;R-Tree索…

[附源码]Python计算机毕业设计Django在线票务系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

JavaEE

文章目录前言JRE与JDK区别JAVASE、JAVAEE、JAVAME区别Dos常用命令为什么需要Path环境变量配置前言 &#x1f4cb;前言&#x1f4cb; &#x1f49d;博客&#xff1a;【无聊大侠hello word】&#x1f49d; ✍有一点思考&#xff0c;有一点想法&#xff0c;有一点理性&#xff01;…

关于有限元应力结果精度的几点讨论

1引言 作为一名汽车结构CAE工程师&#xff0c;使用有限元法进行应力分析是我多年的日常工作。但是关于有限元应力结果的一些技术点一直未能吃透&#xff0c;查到的相关文献也不多&#xff0c;文献内容也存在很多不尽不实之处。最近一段时间&#xff0c;抽空重新读了一遍王勖成…

泊松分布一

文章目录1. 泊松分布定义2.泊松分布具体实例实例1&#xff1a;实例2&#xff1a;3.生成泊松分布的代码泊松分布适合于描述单位间隔(时间、距离、面积、体积)内随机事件发生的次数的概率分布。如电话交换机接到呼叫的次数、汽车站台的候客人数、机器出现的故障数、自然灾害发生的…

【Android】用无障碍服务整个脚本——我看刑

本文灵感来源&#xff1a;李跳跳真实好友 app 目录无障碍服务(AccessibilityService)模拟点击组件ID & 组件文本坐标后台保活效果图存在缺陷缺陷一缺陷二缺陷三缺陷四无障碍服务(AccessibilityService) 无障碍服务(AccessibilityService)&#xff0c;是Google推出为了帮助…

从零搭建Sentry

前言 Sentry 为一套开源的应用监控和错误追踪的解决方案。这套解决方案由对应各种语言的 SDK 和一套庞大的数据后台服务组成。应用需要通过与之绑定的 token 接入 Sentry SDK 完成数据上报的配置。通过 Sentry SDK 的配置&#xff0c;还可以上报错误关联的版本信息、发布环境。…

四信机房环境监测方案上线 实现集中监控,统一管理

随着“东数西算”工程和新基建的加速落地&#xff0c;数智化技术正逐渐渗透到各领域。以机房行业为例&#xff0c;由于数据中心建设规模的逐步壮大&#xff0c;机房设备市场需求同步增长&#xff0c;为行业用户带来更多可能性。 伴随着机房中设备数量不断增多&#xff0c;如何…

Vue2实现浏览器ctrl+f功能

Vue2实现浏览器ctrlf功能 安装插件 使用一个Vue2的插件search-bar-vue2 npm install search-bar-vue2全局注册 //全局注册 import SearchBar from search-bar-vue2 Vue.use(SearchBar)局部注册 <template><div><search-bar :root"#app" :highlig…