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

news/2024/5/14 3:26:58/文章来源:https://blog.csdn.net/m0_73443478/article/details/128237830

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.luyixian.cn/news_show_232497.aspx

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

相关文章

玩好.NET高级调试,你也要会写点汇编

一&#xff1a;背景 1. 简介 .NET 高级调试要想玩的好&#xff0c;看懂汇编是基本功&#xff0c;但看懂汇编和能写点汇编又完全是两回事&#xff0c;所以有时候看的多&#xff0c;总手痒痒想写一点&#xff0c;在 Windows 平台上搭建汇编环境不是那么容易&#xff0c;大多还是…

web课程设计:HTML非遗文化网页设计题材【京剧文化】HTML+CSS+JavaScript

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

提高技术质量标准 | Google Play 持续打造优质平台

作者 / Google Play 统筹产品经理 Lauren Mytton在上一篇文章中&#xff0c;我们为大家总结了 Google Play 在近期将要推出多项新功能&#xff0c;接下来我们将会陆续展开逐一详细说明。应用质量是我们在 Google Play 所做一切努力的基础。Android 用户希望从他们下载的应用和游…

kubernetes 1.18 部署 ingress-nginx

文章目录kubernetes 1.18 部署 ingress-nginx1. 下载 yaml 文件2. 安装 ingress-nginx3. 检查安装情况4. 测试验证4.1 查看ingress规则4.2 访问测试5. 其他内容kubernetes 1.18 部署 ingress-nginx 1. 下载 yaml 文件 在 GitHub 下载完成之后可以直接使用&#xff0c;不需要修…

Linux 部署主从DNS服务器

几个概念&#xff1a; 域名解析为IP地址&#xff1a;正向解析 IP地址解析为域名&#xff1a;反向解析 主DNS服务器&#xff1a;在特定区域内具有唯一性&#xff0c;负责维护该区域内的域名和IP地址之间的对应关系。 从DNS服务器&#xff1a;从服务器中获得域名和IP地址对应关系…

Android桌面图标快捷方式

一、背景 长按桌面图标实现快捷方式最早是iOS提供的功能,而Android最早在Android 7.1版本也提供了对这方面的支持,于是在短时间内,像微信,支付宝,头条等流量级应用都提供了这方面的支持,如下图。 现在,长按桌面图标快捷方式已经是很成熟的功能,实现上也比较简单,主…

爆火的OpenAi的ChatGPT聊天机器人注册和使用攻略

先来看看他的效果怎木样: 哇塞!是不是很奈斯!!! 一. 对OpenAi进行注册登录(需要翻墙) OpenAI APIAn API for accessing new AI models developed by OpenAIhttps://beta.openai.com/ 二. 购买一个虚拟号码用于手机号注册 nullReceive sms online on virtual numbers of SMS…

五、卷积神经网络CNN5(图像卷积与反卷积)

图像卷积 首先给出一个输入输出结果那他是怎样计算的呢&#xff1f; 卷积的时候需要对卷积核进行 180 的旋转&#xff0c;同时卷积核中心与需计算的图像像素对齐&#xff0c;输出结构为中心对齐像素的一个新的像素值&#xff0c;计算例子如下&#xff1a;这样计算出左上角(即第…

[附源码]Python计算机毕业设计Django智能衣橱APP

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

一次nginx “time out”故障排查

研发请求协助排查一个nginx故障。 描述如下&#xff1a; 在内部环境测试没问题。 打包到生产环境后&#xff0c;访问nginx接口地址超时。 研发比对后怀疑是nginx版本不一致导致。内部版本1.23.2&#xff0c;生产环境1.23.1. 收到信息第一感觉不是nginx的问题。不过先测试一…

-aop-

文章目录一.动态代理实现invocationHandler二.AOP概述环绕通知Pointcut定义切入点一.动态代理实现invocationHandler 动态代理&#xff1a;可以在程序的执行过程中&#xff0c;创建代理对象。 通过代理对象执行方法&#xff0c;给目标类的方法增加额外的功能&#xff08;功能增…

华硕编程竞赛11月JAVA专场 A题自由弹簧 题解

作者主页&#xff1a;Designer 小郑 作者简介&#xff1a;软件工程师一枚&#xff0c;来自浙江宁波&#xff0c;负责开发管理公司OA项目&#xff0c;专注软件前后端开发&#xff08;Vue、SpringBoot和微信小程序&#xff09;、系统定制、远程技术指导。CSDN学院、蓝桥云课认证讲…

Android 中的广播机制

一、Android广播概念&#xff1a; 在Android中&#xff0c;有一些操作完成以后&#xff0c;会发送广播&#xff0c;Android系统内部产生这些事件后广播这些事件&#xff0c;至于广播接收对象是否关心这些事件&#xff0c;以及它们如何处理这些事件&#xff0c;都由广播接收对象…

高通Ride软件开发包使用指南(2)

高通Ride软件开发包使用指南&#xff08;2&#xff09;3 Ubuntu系统设置3.1前提条件3.2安装Ubuntu3.3 安装 docker3.4 在Linux主机上安装QNX软件中心3 Ubuntu系统设置 以下步骤准备Ubuntu系统使用docker图像构建工具链SDK&#xff0c;并启用可视化。 3.1前提条件 确保您的电…

【C++ unordered_set set 和 unordered_map 和 map】

文章目录前言简单介绍哈希表&#xff0c;哈希结构什么时候用哈希表unordered_map操作likou第一题 两数之和unordered_set 基础操作unordered_set 实现总结前言 今天重新打开力扣&#xff0c;看到以前的签到题两数之和&#xff0c;以前的方法是双指针暴力解法&#xff0c;偶然看…

CMAKE编译知识

1&#xff0c;Ubuntu安装了cmake之后&#xff0c;直接输入指令查看版本。cmake -version 我这里的版本为3.16.3 2&#xff0c;使用visual studio里面创建一个CMake项目是最快可以看到的。但是一般无法理解。所以我找了网上资料。根据网上所说和自己再试错下。初步了解了cmake…

VMware Workstation 17.0 Pro SLIC Unlocker for Linux

VMware_Dell_2.6_BIOS-EFI64_Mod&#xff1b;macOS Unlocker&#xff0c;支持 macOS Ventura 请访问原文链接&#xff1a;VMware Workstation 17.0 Pro SLIC & Unlocker for Windows & Linux&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&a…

了解常见的模拟器及交换机的基本配置

了解常见的模拟器及交换机的基本配置 1. 首先我们先了解常见的模拟器软件 1.Cisco Packet Tracer&#xff08;简单&#xff0c;纯软件实现&#xff09; Cisco Packet Tracer 是由Cisco公司发布的一个辅助学习工具&#xff0c;为学 习思科网络课程的初学者去设计、配置、排除…

【语音处理】基于自适应差分脉冲编码调制(ADPCM)的实现研究附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步进步&#xff0c;matlab项目目标合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信息&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算…

vue3中的四种插槽的介绍-保证让你看看的明明白白!

插槽 当组件中只有一个插槽的时候&#xff0c;我们可以不设置 slot 的 name 属性。 v-slot 后可以不带参数&#xff0c;但是 v-slot 在没有设置 name 属性的时候&#xff0c; 插槽口会默认为“default”。 插槽主要是在封装组件的时候去使用 注意点&#xff1a;v-slot 只能添加…