Qt Concurrent框架详解(QFuture、QFutureWatcher)

1.概述

Qt Concurrent是Qt提供的一个并发编程框架,用于简化多线程和并行计算的开发。它提供了一组易于使用的函数和类,可以方便地在多线程环境下处理并发任务。

有以下特点:

简单易用:Qt Concurrent提供了一组高级函数和类,使多线程和并行计算变得简单易用。开发者无需显式地创建和管理线程,而是通过调用Qt Concurrent提供的函数实现并发任务。

自动任务分割:Qt Concurrent能够根据可用的线程数自动将大的问题拆分成更小的任务,并分配给不同的线程并行执行。这样能够最大程度地利用系统资源,提高并发执行效率。

异步计算:Qt Concurrent提供了异步执行任务的机制,可以在后台执行任务,同时不会阻塞主线程,从而提高用户界面的响应性。 主要的类和函数:

  • QFuture:表示一个异步任务的未来结果。可以通过调用QFuture的result()方法来获取结果。还可以使用QFutureWatcher类来监视并处理异步任务的结果。
  • QFutureIterator:用于遍历QFuture所代表的异步任务的结果集合。
  • QThread:Qt Concurrent内部会自动管理线程,不需要手动创建和管理线程。但如果需要更细粒度的控制线程的操作,可以使用QThread类。
  • QtConcurrent::run():用于在后台线程执行函数。它会自动创建一个新的线程,并在该线程中执行指定的函数。
  • QtConcurrent::map():用于并行计算,将一个函数应用于一个容器中的每个元素,并返回结果集。它会根据可用的线程数自动进行任务分割和分配。
  • QtConcurrent::filter():根据指定的谓词函数,在容器中筛选符合条件的元素。也会进行任务分割和分配。
  • QtConcurrent::blockingMapped():与map类似,但是会阻塞当前线程直到所有任务完成。

2.常用方法

在 pro 文件添加“Qt += concurrent”并且在我们的 h 文件添加“#include <QtConcurrent>”,就可以使用这些函数了。基本上所有的 concurrent 函数分为三种类型:

  • run 相关:执行函数用;
  • map 相关:处理容器中的每一项;
  • filter 相关:筛选容器中的每一项。

run方法:创建一个新的线程,并在该线程中执行指定的函数。

  • QFuture<T> run(Function function, ...)
  • QFuture<T> run(QThreadPool *pool, Function function, ...)

map方法:在单独的线程里对容器中的每一项进行操作,并返回结果集。

  • QtConcurrent::map():直接操作容器中的每一项。
  • QtConcurrent::mapped():操作容器中的每一项,将处理结果返回一个新的容器,原容器不变。
  • QtConcurrent::mappedReduced():在 mapped() 的基础上将处理结果进一步传递给一个函数继续处理。

filter方法:filter 相关函数和 map 相关函数类似,也是对容器中的元素进行处理,但 filter 更多侧重筛选元素。

  • QtConcurrent::filter()
  • QtConcurrent::filtered()
  • QtConcurrent::filteredReduced()

3.示例

示例1:将普通函数运行在两个不同的线程中,使用QFuture的result()方法来获取返回结果。

#include <QApplication>
#include <QFuture>
#include <QtConcurrent>

QString func1()
{
    qDebug()<<"我是func1函数";
}
QString func2(QString name)
{
    qDebug()<<"我是func2函数";
    return name;
}

int main(int argc, char *argv[])
{
    QCoreApplication  a(argc, argv);

    //用QFuture获取该函数的运行结果
    QFuture<QString> fut1 = QtConcurrent::run(func1);

    //参数2:向func函数传递的参数
    QFuture<QString> fut2 = QtConcurrent::run(func2, QString("func2"));
    QString result2 = fut2.result();
    fut1.waitForFinished();
    fut2.waitForFinished();

    qDebug()<<"result2 = "<<result2;

    return a.exec();
}

运行结果:

示例2: 使用QtConcurrent::map(),QtConcurrent::mapped() ,QtConcurrent::mappedReduced()

map:直接操作容器中的每一项,不返回。

mapped:操作容器中的每一项,将处理结果返回一个新容器,原容器不变。

mappedReduced:mapped() 的基础上将处理结果进一步传递给下一个函数继续处理。

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QFuture>
#include <QtConcurrent>


void processString1(QString& str) {
    str = str.toUpper();   //转大写
}

QString processString2(const QString& str) {
    // 模拟一些复杂的处理逻辑
    QThread::msleep(1000);  // 延迟1秒
    return str.toUpper();   //转大写
}


void processString3(QString &result, const QString &intermedia)
{
    result += " ";
    result += intermedia;
}


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QStringList strings1 = {"hello", "world", "qt", "concurrent"};
    QFuture<void> fut1 = QtConcurrent::map(strings1, processString1);
    fut1.waitForFinished();
    qDebug()<<"==========result1=========";
    for(const QString& result : strings1) {
       qDebug() << result;
    }
    qDebug()<<"==========result1=========";

    qDebug()<<"==========result2=========";
    QStringList strings2 = {"hello", "world", "qt", "concurrent"};
    QFuture<QString> future = QtConcurrent::mapped(strings2, processString2);
    future.waitForFinished();
    QList<QString> results = future.results();
    for(const QString& result : results) {
       qDebug() << result;
    }
    qDebug()<<"==========result2=========";

    qDebug()<<"==========result3=========";
    QStringList strings3 = {"hello", "world", "qt", "concurrent"};
    QFuture<QString> future2 = QtConcurrent::mappedReduced(strings3, processString2,processString3);
    future2.waitForFinished();
    QList<QString> results2 = future2.results();
    for(const QString& results : results2) {
       qDebug() << results;
    }
    qDebug()<<"==========result3=========";
}

MainWindow::~MainWindow()
{
    delete ui;
}

运行结果:

 示例3:使用QFutureWatcher来监视并处理异步任务的结果。

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QFuture>
#include <QtConcurrent>
#include <QFutureWatcher>

QFutureWatcher<QStringList> watcher;

QStringList processString(const QStringList& str) {
    // 模拟一些复杂的处理逻辑
    QThread::msleep(1000);  // 延迟1秒

    QStringList ret;
    for(int i=0;i<str.size();i++)
    {
        ret.append(str.at(i).toUpper());
    }

    return ret;
}

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QStringList strings = {"hello", "world", "qt", "concurrent"};
    QFuture<QStringList> future = QtConcurrent::run(processString, strings);
    watcher.setFuture(future);

    QObject::connect(&watcher, &QFutureWatcher<void>::finished, this, [&]() {
        qDebug() << "All tasks finished!";

        for(const QString& result2 : watcher.result()) {
           qDebug() << result2;
        }
    });

    QObject::connect(&watcher, &QFutureWatcher<void>::progressValueChanged, [](int value) {
        qDebug() << "Progress: " << value << "%";
    });

}

MainWindow::~MainWindow()
{
    delete ui;
}

运行结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/112504.html

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

相关文章

数据库-索引

概念&#xff1a; Mysql 索引 事务 存储引擎 索引&#xff1a;索引是一个排序的列表&#xff0c;列表当中存储的是索引的值和包含这个值的数据所在行的物理地址 索引的作用&#xff1a;就好比书的目录&#xff0c;加快查询的速度 概念图&#xff1a; 索引的作用&#xff1a…

第四章 应用SysML基本特性集的汽车示例 P1|系统建模语言SysML实用指南学习

仅供个人学习记录 汽车模型 主要就是应用练习建模了 Automobile Domain包 用于组织模型的包图 将模型组织入包的包图 需求图捕获汽车规范 汽车规范中包含系统需求的需求图 块定义图定义车辆及其外部环境 汽车域块定义图 用例图表示操作车辆 描述车辆主要功能的用…

uniapp中APP端使用echarts用formatter设置y轴保留2位小数点不生效

uniapp使用echarts&#xff0c;在内置浏览器中&#xff0c;设置保留2位小数能正常显示&#xff08;代码如下&#xff09;&#xff0c;但是在APP端这个设置不起作用。 yAxis: {type: value,axisLabel: {formatter: function (val) {return val.toFixed(2); //y轴始终保留小数点…

【Java 进阶篇】Java Web开发:实现验证码功能

在Web应用程序中&#xff0c;验证码&#xff08;CAPTCHA&#xff09;是一种常见的安全工具&#xff0c;用于验证用户是否为人类而不是机器。验证码通常以图像形式呈现&#xff0c;要求用户在登录或注册时输入正确的字符。在这篇文章中&#xff0c;我们将详细介绍如何在Java Web…

Ubuntu 搭建 DHCP ivp6 server 步骤

Ubuntu 搭建 DHCP ivp6 server 步骤 安装 DHCP server安装 radvd&#xff08;实现局域网路由功能)测试运行 安装 DHCP server apt 安装 isc-dhcp-server sudo apt-get install isc-dhcp-server修改配置文件 /etc/dhcp/dhcpd6.conf 内容如下&#xff1a; lease-time 7200; lo…

如何在idea中使用maven搭建tomcat环境

目录 一、创建maven项目 二、完善代码结构 三、引入依赖和插件 四、启动tomcat&#xff0c;运行项目 &#xff08;1&#xff09;点击添加配置 &#xff08;2&#xff09;点击左上角的加号&#xff0c;选择maven &#xff08;3&#xff09;输入运行命令 五、验证 一、创建…

GB28181学习(十四)——语音广播与语音对讲

语音对讲 定义 用户端向设备通过视音频点播请求音频数据&#xff1b;用户端接收音频数据并通过特定的播放设备&#xff08;如音响&#xff09;播放&#xff1b;用户端向设备发送广播请求&#xff1b;设备解析广播成功后通过INVITE方法向用户请求音频数据&#xff1b;用户通过音…

Android studio进入手机调试状态

首先usb插入电脑手机打开开发者模式进入点击就会在你的页面显示了

ARL灯塔安装与使用

ARL灯塔安装与使用 1. 系统要求2. ARL灯塔安装2.1. docker环境安装2.1.1. 更新yum包2.1.2. 卸载老版docker2.1.3. 安装docker所需要的依赖包2.1.4. 设置yum源2.1.5. 查看仓库中docker版本2.1.6. 安装docker最新版2.1.7. docker设置2.1.8. docker其它命令 2.2. 安装docker-compo…

JS(JavaScript) 实现延迟等待(sleep方法)

起因&#xff1a; 只使用 setTimeout 会产生嵌套等方面的问题&#xff0c;达不到想要的效果。 解决方法&#xff1a; 使用 async/await 还有 Promise 相结合的方式来解决问题。 直接上代码&#xff1a; function sleep(time) {return new Promise((resolve) > setTimeout…

SAP MM学习笔记39 - MRP(资材所要量计划)

这一章开始&#xff0c;离开请求书&#xff0c;学点儿新知识啦。 MRP ( Material Requirement Planning ) - 资材所要量计划。 它的位置在下面的调达周期图上来看&#xff0c;就是右上角的 所要量决定那块儿。 1&#xff0c;MRP(资材所要量计划) 的概要 MRP 的主要目的就是 确…

python进程

进程的定义和常用方法 import os from multiprocessing import Process from time import sleepm 1 list1 []def task1(s, name):global mwhile True:sleep(1)m 1print("进程1", m)list1.append(str(m) "task1")print(list1)print("------------…

FedAT:异步更新联邦学习方法

文章链接&#xff1a;FedAT: A Communication-Efficient Federated Learning Method with Asynchronous Tiers under Non-IID Data 发表会议: SC’21 (International Conference for High Performance Computing, Networking, Storage, and Analysis) 高性能计算&#xff0c;体…

网络套接字编程(二)

网络套接字编程(二) 文章目录 网络套接字编程(二)简易TCP网络程序服务端创建套接字服务端绑定IP地址和端口号服务端监听服务端运行服务端网络服务服务端启动客户端创建套接字客户端的绑定和监听问题客户端建立连接并通信客户端启动程序测试单执行流服务器的弊端 多进程版TCP网络…

scrapy-redis分布式爬虫(分布式爬虫简述+分布式爬虫实战)

一、分布式爬虫简述 &#xff08;一&#xff09;分布式爬虫优势 1.充分利用多台机器的带宽速度 2.充分利用多台机器的ip地址 &#xff08;二&#xff09;Redis数据库 1.Redis是一个高性能的nosql数据库 2.Redis的所有操作都是原子性的 3.Redis的数据类型都是基于基本数据…

攻防世界-web-bug

1. 问题描述 没有额外的描述&#xff0c;仅仅是这样的一个登录界面 但是&#xff0c;我们注意到有注册&#xff08;Register&#xff09;和找回密码&#xff08;Findpwd&#xff09;这俩按钮 注册界面如下&#xff1a;需要输入用户名&#xff0c;密码&#xff0c;生日及地址 …

自动曝光算法(第一讲)

序言 失业在家无事&#xff0c;想到以后换方向不做自动曝光了&#xff0c;但是自动曝光的工作经验也不能浪费了&#xff0c;准备写一个自动曝光的教学&#xff0c;留给想做自动曝光的小伙伴参考。笔者当时开发自动曝光没有按摄影的avtvevbvsv公式弄&#xff0c;而是按正确的增…

K-means(K-均值)算法

K-means&#xff08;k-均值&#xff0c;也记为kmeans&#xff09;是聚类算法中的一种&#xff0c;由于其原理简单&#xff0c;可解释强&#xff0c;实现方便&#xff0c;收敛速度快&#xff0c;在数据挖掘、聚类分析、数据聚类、模式识别、金融风控、数据科学、智能营销和数据运…

UML类图关系

1.依赖 依赖关系由箭头表示&#xff0c;含义为A类在类中用到了B类&#xff0c;如B类作为A类的属性、参数、返回值等都属于依赖关系。 2.泛化&#xff08;继承&#xff09; 泛化用三角箭头和直线表示&#xff0c;extend。 3.实现 实现用三角箭头和虚线表示&#xff0c;在…

Mac 配置环境变量

Mac 配置环境变量 修改配置文件 vim ~/.bash_profile i进入编辑模式. Esc&#xff1a;wq 保存文件 esc:q 退出 如&#xff1a;jdk环境变量配置 JAVA_HOME/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/HomeCLASSPATH$JAVA_HOME/lib/tools.jar:$JAVA_HOME/…