使用QtConcurrent编写多线程程序(也可以阻塞)
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Amnes1a/article/details/66470751
Qt在其QtConcurrent命名空间中为我们提供了编写多线程程序的高级API,使用这个API可以使我们在不使用低级的线程元素,如互斥锁,读写锁,条件变量或者信号量的情况下编写出搞笑的多线程程序。并且,使用QtConcurrent编写的程序能够自动地根据当前可以使用的处理器核心数调整实际使用的线程数目。这就意味着我们目前所写的程序即使将来的多核心机器上也能正常运行,并有很好的伸缩性。
QtConcurrent命名空间中包括了用于并行处理的函数式编程API,其中有用于共享内存系统的MapReduce 和 FilterReduce,和用于在GUI程序中管理异步计算的相关类。其中,管理异步计算的几个类,我们在前面已经说过了,即QFuture,QFutureIterator,QFutureWatcher,QFutureSynchronizer。今天,我们主要来看一下MapReduce和FilterReduce方法。
MapReduce相关方法包括:
QtConcurrent::map():这个函数会将作为参数传入的函数应用到容器中的每一项,对这些项进行就地修改。
QtConcurrent::mapped():功能类似于map(),只不过它不是在原来的容器中就地修改,而是将修改后的元素放到一个新的容器中返回。
QtConcurrent::mappedReduce():功能类似于mapped(),只不过它会将修改过的每一项再传入另一个Reduce函数进行简化,将多个结果按某种要求简化成一个。
FilterReduce相关方法包括:
QtConcurrent::filter():从容器中删除那些满足某个过来条件的项。
QtConcurrent::filtered():功能类似于filter(),只不过它会返回一个包含剩余元素的容器。
QtConcurrent::filteredReduced():功能类似于filtered(),只不过那些剩余的元素会被进一步传入一个Reduce() 函数,进行简化。
QtConcurrent命名空间中组合一类函数,就是我们之间讲过的run() 函数。
下面,我们分别通过实例还看一下这些函数的使用方法。先来看Map类方法,代码如下:
#include <QCoreApplication>
#include <QtConcurrent>
#include <QVector>
#include <QDebug>
#include <QFuture>
void testMap(int& num)
{
num += 1;
}
int testMap2(const int& num)
{
return num + 1;
}
void testReduce(int& result, const int& item)
{
result = item > result ? item : result;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QVector<int> vec;
qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
for(int i = 1; i <= 10; i++)
{
vec.push_back(qrand() % 100);
}
qDebug() << "origin: " << vec;
//Map
QFuture<void> f = QtConcurrent::map(vec, testMap);
f.waitForFinished();
qDebug() << "after map: " << vec;
QFuture<int> r = QtConcurrent::mappedReduced(vec, testMap2, testReduce);
qDebug() << "max: " << r.result();
return a.exec();
}
首先,在上面的代码中,我们声明了两个map类函数。testMap()用于QtConcurrent::map(),对容器中的每一项进行就地修改;testMap2()用于QtConcurrent::MappedReduced(),将进行过map的那些元素简化成一个,在此我们是求map后容器中的最大值。注意testMap()和testMap2()的区别。
上面的代码实现的功能很简单。先产生10个随机数存入vector,然后对该vector应用testMap()方法,将容器中的每一项加1,输出加1后的结果;然后我们再对加1处理过的容器应用testMap2()和testReduce(),其中testMap2()会对容器中的每一项再加1,然后将结果传入testReduce()方法,该方法找出当前容器中的最大值。运行结果如下:
下面,我们再来简单看下Filter类函数,还是先上代码:
#include <QCoreApplication>
#include <QtConcurrent>
#include <QVector>
#include <QDebug>
#include <QFuture>
void testReduce(int& result, const int& item)
{
result = item > result ? item : result;
}
bool testFilter(const int& item)
{
return item >= 50;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QVector<int> vec;
qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
for(int i = 1; i <= 10; i++)
{
vec.push_back(qrand() % 100);
}
qDebug() << "origin: " << vec;
//Filter
QFuture<void> f = QtConcurrent::filter(vec, testFilter);
f.waitForFinished();
qDebug() << "after filter: " << vec;
QFuture<int> r = QtConcurrent::filteredReduced(vec, testFilter, testReduce);
qDebug() << "max: " << r.result();
return a.exec();
}
实现的功能和上面一下,将产生的随机数先进行过滤,在找出最大值。运行结果如下:
当然,这里只是简单的演示一下该命名空间中常用函数的使用方法。大家主要要注意MapFunction、FilterFunction、ReduceFunction的声明,形式不能错。
另外,上面演示的这些函数都是QtConcurrent命名空间中的非阻塞函数。其实,在该命名空间中还提供了一系列的阻塞函数。声明信息如下:
void blockingFilter(Sequence &sequence, FilterFunction filterFunction)
Sequence blockingFiltered(const Sequence &sequence, FilterFunction filterFunction)
Sequence blockingFiltered(ConstIterator begin, ConstIterator end, FilterFunction filterFunction)
T blockingFilteredReduced(const Sequence &sequence, FilterFunction filterFunction, ReduceFunction reduceFunction, QtConcurrent::ReduceOptions reduceOptions = UnorderedReduce | SequentialReduce)
T blockingFilteredReduced(ConstIterator begin, ConstIterator end, FilterFunction filterFunction, ReduceFunction reduceFunction, QtConcurrent::ReduceOptions reduceOptions = UnorderedReduce | SequentialReduce)
void blockingMap(Sequence &sequence, MapFunction function)
void blockingMap(Iterator begin, Iterator end, MapFunction function)
T blockingMapped(const Sequence &sequence, MapFunction function)
T blockingMapped(ConstIterator begin, ConstIterator end, MapFunction function)
T blockingMappedReduced(const Sequence &sequence, MapFunction mapFunction, ReduceFunction reduceFunction, QtConcurrent::ReduceOptions reduceOptions = UnorderedReduce | SequentialReduce)
T blockingMappedReduced(ConstIterator begin, ConstIterator end, MapFunction mapFunction, ReduceFunction reduceFunction, QtConcurrent::ReduceOptions reduceOptions = UnorderedReduce | SequentialReduce)
这些函数的使用方式和上面演示的非阻塞函数类似,在此就不一一演示了,大家可以自行测试,或使用上面我给出的例子进行测试。
---------------------
作者:求道玉
来源:CSDN
原文:https://blog.csdn.net/Amnes1a/article/details/66470751
版权声明:本文为博主原创文章,转载请附上博文链接!
使用QtConcurrent编写多线程程序(也可以阻塞)的更多相关文章
- (转)Ubuntu下用eclipse cdt编写多线程程序的简单设置
在Ubuntu下用eclipse cdt编写了一个多线程程序,但是总是出现pthread_create函数未定义! 查找了下原因,原来是要对eclipse进行一些简单的设置: 右键单击项目->P ...
- windows qt 使用c++ posix接口编写多线程程序(真神奇)good
一.多线程是多任务处理的一种特殊形式,多任务处理允许让电脑同时运行两个或两个以上的程序.一般情况下,两种类型的多任务处理:基于进程和基于线程.基于进程的多任务处理是程序的并发执行.基于线程的多任务处理 ...
- Java 中,编写多线程程序的时候你会遵循哪些最佳实践?
这是我在写 Java 并发程序的时候遵循的一些最佳实践: a)给线程命名,这样可以帮助调试. b)最小化同步的范围,而不是将整个方法同步,只对关键部分做同步. c)如果可以,更偏向于使用 volati ...
- Linux多线程实践(10) --使用 C++11 编写 Linux 多线程程序
在这个多核时代,如何充分利用每个 CPU 内核是一个绕不开的话题,从需要为成千上万的用户同时提供服务的服务端应用程序,到需要同时打开十几个页面,每个页面都有几十上百个链接的 web 浏览器应用程序,从 ...
- 使用C++编写linux多线程程序
前言 在这个多核时代,如何充分利用每个 CPU 内核是一个绕不开的话题,从需要为成千上万的用户同时提供服务的服务端应用程序,到需要同时打开十几个页面,每个页面都有几十上百个链接的 web 浏览器应用程 ...
- [转]使用 C++11 编写 Linux 多线程程序
前言 在这个多核时代,如何充分利用每个 CPU 内核是一个绕不开的话题,从需要为成千上万的用户同时提供服务的服务端应用程序,到需要同时打开十几个页面,每个页面都有几十上百个链接的 web 浏览器应用程 ...
- 如何提高多线程程序的cpu利用率
正如大家所知道的那样,多核多cpu越来越普遍了,而且编写多线程程序也是件很简单的事情.在Windows下面,调用CreateThread函数一次就能够以你想要的函数地址新建一个子线程运行.然后,事情确 ...
- OO学习体会与阶段总结(多线程程序)
前言 在最近一个月的面向对象编程学习中,我们进入了编写多线程程序的阶段.线程的创建.调度和信息传递,共享对象的处理,线程安全类的编写,各种有关于线程的操作在一定程度上增加了近三次作业的复杂度与难度,带 ...
- 通过编写聊天程序来熟悉python中多线程及socket的用法
1.引言 Python中提供了丰富的开源库,方便开发者快速就搭建好自己所需要的应用程序.本文通过编写基于tcp/ip协议的通信程序来熟悉python中socket以及多线程的使用. 2.python中 ...
随机推荐
- java学习路线-Java技术人员之路从0基础到高级
满满的 全是干货 java基础: 尚学堂 马士兵 个人推荐 历经5年锤练--史上最适合刚開始学习的人入门的Java基础视频 很具体 适合 时间多的看 传智播客java基础班 马士兵线程 ...
- 1高并发server:多路IO之select
1 select A:select能监听的文件描写叙述符个数受限于FD_SETSIZE,一般为1024.单纯改变进程打开 的文件描写叙述符个数并不能改变select监听文件个数 B:解决1024 ...
- 虚拟机安装Ubuntu 12.04 出现提示“Ubuntu is running in low-graphics mode?”
原文链接: http://blog.csdn.net/maimang1001/article/details/17048273 http://blog.csdn.net/bluetropic/arti ...
- spring学习笔记(五)
1.后置通知 需求:调用相应业务方法后,完成资源的关闭. a. 在beans.xml中配置 .... <beans> <!--配置被代理对象--> <bean id=&q ...
- LightOJ 1070 - Algebraic Problem 矩阵高速幂
题链:http://lightoj.com/volume_showproblem.php?problem=1070 1070 - Algebraic Problem PDF (English) Sta ...
- activiti自己定义流程之整合(三):整合自己定义表单创建模型
本来在创建了表单之后应该是表单列表和预览功能.可是我看了看整合的代码,和之前没实用angularjs的基本没有什么变化,一些极小的变动也仅仅是基于angularjs的语法,因此全然能够參考之前说些的表 ...
- 生产环境中 Ngx_lua 使用技巧和应用的范例
生产环境中 Ngx_lua 使用技巧和应用的范例 时间 -- :: 51CTO技术博客 原文 http://rfyiamcool.blog.51cto.com/1030776/1252501 主题 L ...
- 使用 NGUI Toggle 制作单选框
好久没写了,今天来把关于NGUI的做的简单功能发上来~ 这个是做单选框的.用了新版本的NGUI后,发现没有以前的Checkbox了,在网上查了之后才知道是用Toggle代替了以前的Checkbox.现 ...
- ios 2017启动页(Launch Screen Images)、图标(App Icon)尺寸大小
ios 2017启动页(Launch Screen Images).图标(App Icon)尺寸大小 iPhone Portrait iOS 8,9-Retina HD 5.5 (1242×220 ...
- 服务器之ipmitool
一般命令 raw #发送一个原始的IPMI请求,并且打印回复信息. Lan #配置网络(lan)信道(channel) chassis #查看底盘的状态和设置电源 event #向BMC发送一个已经定 ...