Qt中的 Concurrent 模块为我们提供了在一个序列容器类型针对每一个元素的多线程并行运算,比如 QList 、 QVector 。

  • QtConcurrent::map() :对序列的每一项元素都应用一个函数,并将运算结果替换原来的元素。
  • QtConcurrent::mapped() :功能类似 map() 函数,它会返回一个新容器存储函数处理后的结果。
  • QtConcurrent::mappedReduced() :类似于 mapped() ,他会将这个返回的结果序列,经过另一个函数处理为一个单个的值。

1. map 和 mapped

QtConcurrent::map 和 QtConcurrent::mapped 的基本形式如下:

QFuture<void> map(Sequence &sequence, MapFunctor map)

  • 参数 sequence :表示序列容器(如QList、QVector等)
  • 参数 map :表示函数。函数的形式必须符合 U function(T &t); 形式。
    类型 U 和 T 可以为任何类型,但是 T 的类型必须与容器中的类型保持一致。返回值 U QtConcurrent::map 函数中并没有用到。
  • 返回值 QFuture<void> 。关于 QFuture 这里就不过多介绍了,了解更多可以参考上一篇文章 QtConcurrent多线程 - run()与QFuture

下面是一个简单的使用示例:

1 void scale(QImage &image)
2 {
3     image = image.scaled(100, 100);
4 }
5
6 QList<QImage> images = ...;
7 QFuture<void> future = QtConcurrent::map(images, scale);

该示例中,多线程对 QList<QImage> 容器中的每一个 QImage 缩放到 100 * 100 的尺寸。结果会覆盖掉原容器中的元素。


QtConcurrent::mapped 函数跟 QtConcurrent::map 函数类似,不同之处在于:

  1. 传递的函数形式不同。它的形式为, U function(const T &t); ,一个常引用做为参数,表示容器中的元素不可修改。返回值 U 存入整个 QtConcurrent::mapped 计算后的新容器中返回。
  2. 函数 QtConcurrent::mapped 的返回值为 QFuture<U> ,QFuture 除了可以表示单个类型也可以一组序列容器类型,跟单个的类似,可以使用 results 函数返回运算后的结果。

下面是使用 QtConcurrent::mapped 的例子

1 QImage scaled(const QImage &image)
2 {
3     return image.scaled(100, 100);
4 }
5
6 QList<QImage> images = ...;
7 QFuture<QImage> thumbnails = QtConcurrent::mapped(images, scaled);

这里同样也是对列表中的 QImage 进行缩放到 100 * 100 大小,但是容器本身的内容没有改变。
使用如下代码获取运算结果:

1 funcFunture2.waitForFinished();        // 等待运算处理完成
2 thumbnails.results();                // 获取运算结果

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

2. mappedReduced

mappedReduced() 类似于 QtConcurrent::mapped() ,但是它不是返回一个带有新结果的序列,而是使用reduce函数将结果组合成一个单独的值。

它的函数基本形式如下:

1 template <typename Sequence, typename MapFunctor, typename ReduceFunctor>
2 QFuture<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType>
3 mappedReduced(const Sequence &sequence,
4               MapFunctor map,
5               ReduceFunctor reduce,
6               ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))
  • 参数 sequence :表示序列容器。
  • 参数 map :同 mapped 函数,形式为 U function(const T &t); 的函数。
  • 参数 reduce :处理返回后的结果序列的函数。形式为 V function(T &result, const U &intermediate) , T 为最终结果类型, U 为 map 函数的返回类型,V mappedReduced 并没有使用此返回值。
  • 参数 options :reduce 函数的执行顺序,默认为任意顺序。设置为 OrderedReduce 表示按照原始序列的顺序执行。而 SequentialReduce 则表示同一时刻,只有一个线程在执行 reduce 函数,设置为此标志时,可以不用对 reduce 函数进行加锁操作。
  • 返回值: 返回 QFuture<T> ,这个 T 类型就是 reduce 中的第一个参数。

下面是一个示例:

 1 void addToCollage(QImage &collage, const QImage &thumbnail)2 {3     QPainter p(&collage);4     static QPoint offset = QPoint(0, 0);5     p.drawImage(offset, thumbnail);6     offset += ...;7 }8 9 QList<QImage> images = ...;
10 QFuture<QImage> collage = QtConcurrent::mappedReduced(images, scaled, addToCollage);

这里 images 中的每一个元素执行完 scaled 函数后的序列,序列中的每一个元素再执行函数 addToCollage ,最后将计算结构返回。


3. 其他扩展

使用迭代器作为序列容器的输入范围。

1 QList<QImage> images = ...;
2
3 QFuture<QImage> thumbnails = QtConcurrent::mapped(images.constBegin(), images.constEnd(), scaled);
4
5 // map in-place only works on non-const iterators
6 QFuture<void> future = QtConcurrent::map(images.begin(), images.end(), scale);
7
8 QFuture<QImage> collage = QtConcurrent::mappedReduced(images.constBegin(), images.constEnd(), scaled, addToCollage);

阻塞等待形式

map 、mapped和mappedReduced为非阻塞形式的多线程执行,可以使用 QFuture 和 QFutureWatcher 作异步通知。但是Qt同样也提供了阻塞版本的函数:

1 QList<QImage> images = ...;
2
3 // each call blocks until the entire operation is finished
4 QList<QImage> future = QtConcurrent::blockingMapped(images, scaled);
5
6 QtConcurrent::blockingMap(images, scale);
7
8 QImage collage = QtConcurrent::blockingMappedReduced(images, scaled, addToCollage);

这里需要注意的是,他们的返回值不是 QFuture ,而是真实的结果类型。(在这个示例中,返回 QImage 和 QList<QImage>)

使用类的成员函数

 1 // squeeze all strings in a QStringList2 QStringList strings = ...;3 QFuture<void> squeezedStrings = QtConcurrent::map(strings, &QString::squeeze);4 5 // swap the rgb values of all pixels on a list of images6 QList<QImage> images = ...;7 QFuture<QImage> bgrImages = QtConcurrent::mapped(images, &QImage::rgbSwapped);8 9 // create a set of the lengths of all strings in a list
10 QStringList strings = ...;
11 QFuture<QSet<int> > wordLengths = QtConcurrent::mappedReduced(string, &QString::length, &QSet<int>::insert);

仿函数

 1 struct Scaled2 {3     Scaled(int size) : m_size(size) { }4     typedef QImage result_type;5 6     QImage operator()(const QImage &image)7     {8         return image.scaled(m_size, m_size);9     }
10
11     int m_size;
12 };
13
14 QList<QImage> images = ...;
15 QFuture<QImage> thumbnails = QtConcurrent::mapped(images, Scaled(100));

对于 reduce 函数,不直接支持函数对象。但是,当显式指定约简结果的类型时,可以使用仿函数:

 1 struct ImageTransform2 {3     void operator()(QImage &result, const QImage &value);4 };5 6 QFuture<QImage> thumbNails =7 QtConcurrent::mappedReduced<QImage>(images,8                                     Scaled(100),9                                     ImageTransform(),
10                                     QtConcurrent::SequentialReduce);

lambda或使用std::bind,处理多参数函数

比如这个函数

QImage QImage::scaledToWidth(int width, Qt::TransformationMode) const;

可以借助 lambda 表达式处理参数

1 QList<QImage> images = ...;
2 std::function<QImage(const QImage &)> scale = [](const QImage &img) {
3     return img.scaledToWidth(100, Qt::SmoothTransformation);
4 };
5 QFuture<QImage> thumbnails = QtConcurrent::mapped(images, scale);

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

Qt QtConcurrent多线程 - map、mapped和mappedReduced相关推荐

  1. QtConcurrent的基础用法map,mapped,mappedReduced

    实际上应该说多线程让QtConcurrent实现了并行可能更准确点.不然map函数就不好理解了.那么QtConcurrent的map函数又有什么用呢?这就要先看看map的参数了.map函数有两个参数, ...

  2. QT 中多线程实现方法总结

    第一: 用QtConcurrentRun类,适合在另一个线程中运行一个函数.不用继承类,很方便 第二:用QRunnable和QThreadPool结合.继承QRunnable,重写run函数,然后用Q ...

  3. Qt中多线程间的同步

    文章目录 1 Qt中多线程间的同步 1 Qt中多线程间的同步 多线程编程的本质是什么? 并发性是多线程编程的本质. 在宏观上,所有线程并行执行. 多个线程间相互独立,互补干涉. 常规解决方案设计: 问 ...

  4. 使用Qt的多线程编程

    Qt的多线程编程 项目简介 项目技术 项目展示 主要源码片段解析 获取完整项目源码传送门 项目简介 我们展示了如何将自定义类型与元对象系统集成在一起,使它们能够存储在QVariant对象中,在调试信息 ...

  5. Qt创建多线程的两种方法

    来源:https://github.com/czyt1988/czyBlog/tree/master/tech/QtThread 1.摘要 Qt有两种多线程的方法,其中一种是继承QThread的run ...

  6. Qt 多线程中地信号与槽

    Qt 多线程中地信号与槽 函数原型: 1 QObject::connect(const QObject *sender, const char *signal, const QObject *rece ...

  7. alin的学习之路:Qt与多线程

    alin的学习之路:Qt与多线程 如果程序在进行复杂的逻辑处理过程中, 对窗口进行操作, 就会出现无响应的情况. 如何解决这样的问题与高并发的问题? 需要使用多线程. 方式1 特点:简单 创建一个自定 ...

  8. 基于QT的多线程视频监控的实现(一)

    <基于QT的多线程视频监控的实现(一)> <基于QT的多线程视频监控的实现(二)> <基于QT的多线程视频监控的实现(三)> 本系统是采用的Windows的开发环境 ...

  9. Qt实现多线程编程的两种方式

    Qt实现多线程编程的两种方式 方式一: 继承自QThread类,覆写run函数.此实现方法只有run函数内的代码是运行在子线程内. 代码示例: #ifndef QDEMOTHREAD_H #defin ...

最新文章

  1. c#启动mysql数据库服务器_C#启动停止SQL数据库服务
  2. stm32产生100k时钟信号_stm32f105/107系统时钟变慢
  3. MSRCR(Multi-Scale Retinex with Color Restore)
  4. 参观移动公司机房感想
  5. java简单烟花代码_JavaScript实现的简单烟花特效代码
  6. zabbix监控华为USG6000防火墙
  7. 小程序引入阿里云图标
  8. 【操作系统原理-陈渝老师】第七章 进程与线程
  9. 故事板(StoryBoards)和动画(Animations)
  10. 原来 Elasticsearch 还可以这么理解
  11. PHPMyWind5.4存储XSS(CVE-2017-12984)
  12. Web前端js实现tif文件浏览(含多页tif)
  13. 如何将Photoshop图层复制到其他文档
  14. giflib加载GIF文件
  15. Manjaro通过deepin/Arch库安装Tim出现版本太低无法登录问题[解决]
  16. args = parser.parse_args()报错
  17. 服务器主板显示e2,大金中央空调有一台机面板显示E2是什么问题如何解决故障...
  18. Flutter一键自动生成并替换图标 Android iOS图标(
  19. 从源码角度分析Android中的Binder机制的前因后果
  20. 金大侠眼光果然犀利:《笑傲江湖》只值一块钱 (转)

热门文章

  1. 关于tomcat中Servlet对象池
  2. AMD Mantle与Media SDK的异同
  3. Python中shodan模块的使用
  4. 详细信息:“从提供程序读取数据时出错:“Could not load file or assembly 'Renci.SshNet, Version=2016.1.0.0, Culture=neutr
  5. 怎样在电脑上填写准考证号码
  6. 墨者X-Forwarded-For注入漏洞实战
  7. SSH服务器一些操作记录
  8. C语言与Windows API编程!有无同路人?
  9. 相遇问题(力扣第462题)
  10. 名画93 马远《水图卷》