版权声明:本文为博主原创文章,未经博主允许不得转载。 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编写多线程程序(也可以阻塞)的更多相关文章

  1. (转)Ubuntu下用eclipse cdt编写多线程程序的简单设置

    在Ubuntu下用eclipse cdt编写了一个多线程程序,但是总是出现pthread_create函数未定义! 查找了下原因,原来是要对eclipse进行一些简单的设置: 右键单击项目->P ...

  2. windows qt 使用c++ posix接口编写多线程程序(真神奇)good

    一.多线程是多任务处理的一种特殊形式,多任务处理允许让电脑同时运行两个或两个以上的程序.一般情况下,两种类型的多任务处理:基于进程和基于线程.基于进程的多任务处理是程序的并发执行.基于线程的多任务处理 ...

  3. Java 中,编写多线程程序的时候你会遵循哪些最佳实践?

    这是我在写 Java 并发程序的时候遵循的一些最佳实践: a)给线程命名,这样可以帮助调试. b)最小化同步的范围,而不是将整个方法同步,只对关键部分做同步. c)如果可以,更偏向于使用 volati ...

  4. Linux多线程实践(10) --使用 C++11 编写 Linux 多线程程序

    在这个多核时代,如何充分利用每个 CPU 内核是一个绕不开的话题,从需要为成千上万的用户同时提供服务的服务端应用程序,到需要同时打开十几个页面,每个页面都有几十上百个链接的 web 浏览器应用程序,从 ...

  5. 使用C++编写linux多线程程序

    前言 在这个多核时代,如何充分利用每个 CPU 内核是一个绕不开的话题,从需要为成千上万的用户同时提供服务的服务端应用程序,到需要同时打开十几个页面,每个页面都有几十上百个链接的 web 浏览器应用程 ...

  6. [转]使用 C++11 编写 Linux 多线程程序

    前言 在这个多核时代,如何充分利用每个 CPU 内核是一个绕不开的话题,从需要为成千上万的用户同时提供服务的服务端应用程序,到需要同时打开十几个页面,每个页面都有几十上百个链接的 web 浏览器应用程 ...

  7. 如何提高多线程程序的cpu利用率

    正如大家所知道的那样,多核多cpu越来越普遍了,而且编写多线程程序也是件很简单的事情.在Windows下面,调用CreateThread函数一次就能够以你想要的函数地址新建一个子线程运行.然后,事情确 ...

  8. OO学习体会与阶段总结(多线程程序)

    前言 在最近一个月的面向对象编程学习中,我们进入了编写多线程程序的阶段.线程的创建.调度和信息传递,共享对象的处理,线程安全类的编写,各种有关于线程的操作在一定程度上增加了近三次作业的复杂度与难度,带 ...

  9. 通过编写聊天程序来熟悉python中多线程及socket的用法

    1.引言 Python中提供了丰富的开源库,方便开发者快速就搭建好自己所需要的应用程序.本文通过编写基于tcp/ip协议的通信程序来熟悉python中socket以及多线程的使用. 2.python中 ...

随机推荐

  1. windows上使用的免费连接linux终端xshell6,xftp6下载

    xshell 6 https://www.netsarang.com/download/down_form.html?code=622 xftp 6 https://www.netsarang.com ...

  2. win10 环境下 MinGW-w64安装

    MinGW-w64 就是 著名C/C++编译器GCC的Windows版本. 一.什么是 MinGW-w64 ?MinGW 的全称是:Minimalist GNU on Windows .它实际上是将经 ...

  3. unity, inspector debug

    以前经常因为脚本中private变量不在inspector界面中显示,不方便观察其值的变化,所以本该用private的用了public. 今天发现,原来inspector有个选项,如图,平常勾选的是N ...

  4. 605. Can Place Flowers【easy】

    605. Can Place Flowers[easy] Suppose you have a long flowerbed in which some of the plots are plante ...

  5. crontab执行脚本与手动执行结果不一致

    反正网上说是环境变量问题,我就直接在脚本第二行加入以下代码: source /etc/profile source ~/.bashrc 问题是解决了!

  6. iOS swift版本无限滚动轮播图

    之前写过oc版本的无限滚动轮播图,现在来一个swift版本全部使用snapKit布局,数字还是pageConrrol样式可选 enum typeStyle: Int { case pageContro ...

  7. SpringMVC请求使用@PathVariable获取文件名称并且文件名中存在.导致路径被截取的问题

    在SpringMVC中,当使用@pathVariable通过Get请求获取路径名称时,如果路径名称上存在小数点,则获取不到小数点后面的内容,会被Spring截取. 比如我获取某一文件,路径是local ...

  8. 做自己生活的导演:华为CameraKit为你加持大师光环

    今年最流行的娱乐方式,无疑是短视频,抖音等短视频平台,越来越多的消费者沉浸其中.除了看别人拍的短视频用以丰富生活乐趣之外,也有不少跃跃欲试的消费者加入到短视频拍摄的行列中.随着拍摄者的增加,对拍摄设备 ...

  9. Cmder 配置使用

    官网下载 配置: 1.把 Cmder 加到环境变量 将Cmder.exe存放的目录添加到系统环境变量path 添加成功后,Win+r 输入cmder,可以正确打开cmder 窗口即可. 2.添加 cm ...

  10. request:getParameter和getAttribute区别

    getParameter 是用来接受用post个get方法传递过来的参数的.getAttribute 必须先setAttribute.(1)request.getParameter() 取得是通过容器 ...