使用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中 ...
随机推荐
- 破解 zip 压缩包程序
目录 项目文件结构 代码实现过程 演示效果 代码地址如下:http://www.demodashi.com/demo/12021.html 项目文件结构 在当前目录有三个文件: 3-zipCrack. ...
- AngularJs学习笔记(3)——scope
AngularJS启动并生成视图时,会将根ng-app元素同$rootScope进行绑定. $rootScope是所有$scope对象的最上层,是AngularJS中最接近全局作用域的对象 . 一个n ...
- 【应用篇】Activiti外置表单实例demo(四)
在这里我想说的外置表单.是说我们将我们自己的jsp(.form,.html)等页面上传到工作流的数据库中,当任务运行到当前结点时.给我们像前台发送绑定好的表单. 此处是给表单绑定表单的过程 water ...
- Linux Chrome Tab 标题 乱码
1. 刚装完ubuntu 14.04 英文版, 又装了google chrome 浏览器. 2. 打开chrome浏览器,发现tab也没的标题是乱码: 3. 而系统自带的firefox却没有这个问题, ...
- Atitit.java jna 调用c++ dll 的总结
Atitit.java jna 调用c++ dll 的总结 1. JNA技术解密1 1.1. JNA工作原理1 2. JNA技术难点 Java—C和操作系统数据类型的对应表1 2.1. 1 2.2. ...
- java中ThreadLocalRandom类和Random类的使用
package frank; import java.lang.*; import java.util.*;//工具类一般都在util里面 import java.util.concurrent.Th ...
- C++语言基础(8)-引用
(重要)使用引用的一些注意点: 1.引用不能绑定临时数据,也不能绑定任何无法获取内存地址的常量,表达式,或值,常引用除外. 第一种写法:(错误) int func_int(){ ; return n; ...
- linux学习之缓存机制
linux中的缓存机制 在Linux系统中,为了提高文件系统性能,内核利用一部分物理内存分配出缓冲区,用于缓存系统操作和数据文件,当内核收到读写的请求时,内核先去缓存区找是否有请求的数据,有就直接返回 ...
- linux学习之vimrc配置推荐
,gb2312,gbk,gb18030,big5 "去掉vi一致性 set nocompatible ""设置行号 set number "打开文件类型自动检测 ...
- JS DOM -- 关于回车键盘事件执行事件
一.需求制作一个模拟对话框, 二. 1.需要发送后,输入框清空 2.按enter键可发送 三.代码部分 <!DOCTYPE HTML> <html> <head> ...