QT多线程的示例

news2024/9/28 5:30:05

想象现在有一个场景,一共有三个线程线程A需要产生1000以内的随机数,线程B需要对这些随机数进行冒泡排序,线程C需要对这些随机数进行快速排序,主线程用来显示线程A的随机数,并且显示线程A和线程B的处理结果,这里我们还可以对比一下快速排序和冒泡排序的速度。
我们设计UI界面如下:
在这里插入图片描述
这个UI界面用到了QListWidget、QPushbutton、QGroupBox控件。
然后我们写三个线程类,把三个线程类都放在MyThread这个文件中,代码如下:

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QThread>
#include <QVector>
#include <QRandomGenerator>
#pragma execution_character_set("utf-8")

class Generate : public QThread
{
    Q_OBJECT
public:
    explicit Generate(QObject *parent = nullptr);

signals:
    void SendArray(QVector<int> num);
public slots:
    void RecviveNum(int num);
protected:
    void run() override;
private:
    int m_num;
};

class MBupple : public QThread
{
    Q_OBJECT
public:
    explicit MBupple(QObject *parent = nullptr);

signals:
    void FinishBupple(QVector<int> flist);
public slots:
    void RecviveNum(QVector<int> rlist);
protected:
    void run() override;
private:
    QVector<int> m_list;
};

class MQuick : public QThread
{
    Q_OBJECT
public:
    explicit MQuick(QObject *parent = nullptr);
signals:
    void FinishQuick(QVector<int> flist);
public slots:
    void RecviveNum(QVector<int> rlist);
protected:
    void run() override;
private:
    QVector<int> m_list;
private:
    void quickSort(QVector<int> &list,int l,int r);
};
#endif // MYTHREAD_H

Generate类用来生成随机数,它有一个槽函数void RecviveNum(int num);这个是用来接收来自主线程发来的随机数的数量,还有一个 void SendArray(QVector num);信号,这个是把生成好的随机数,分别发给主线程显示,和其他两个排序线程排序,void run() override;这个重写基类run函数为了生成随机数,不过这里的随机数并不是真正意义上的随机数,而是伪随机数。
以下是Generate的函数:

Generate::Generate(QObject *parent) : QThread(parent){
}
void Generate::RecviveNum(int num){
    m_num=num;
}
void Generate::run(){
    qDebug()<<"生成随机数的线程ID号为"<<QThread::currentThread();
    QElapsedTimer m_timer;
    m_timer.start();
    QVector<int> randList;
    for(int i=0;i<m_num;i++){
        randList.push_back(qrand()%100000);
    }
    int m_delaytime = m_timer.elapsed();
    qDebug()<<"生成"<<m_num<<"个随机数总共用时:"<<m_delaytime<<"毫秒";
    emit SendArray(randList);
}

MBupple类主要来进行把来自Generate的随机数进行冒泡排序,它的run函数就是冒泡排序,它的FinishBupple函数主要是将排序好的随机数发送给主线程显示,它的RecviveNum函数是拿到来自Generate生成的随机数,以下为实现代码:

MBupple::MBupple(QObject *parent) : QThread(parent{
}
void MBupple::RecviveNum(QVector<int> rlist)
{
    m_list=rlist;
}

void MBupple::run()
{
    qDebug()<<"冒泡排序的线程ID号为"<<QThread::currentThread();
    QElapsedTimer m_timer;
    m_timer.start();
    int temp;
    for(int i=0;i<m_list.size();++i){
        for(int j=0;j<m_list.size()-i-1;++j){
            if(m_list[j]>m_list[j+1]){
                temp=m_list[j];
                m_list[j]=m_list[j+1];
                m_list[j+1]=temp;
            }
        }
    }
    int m_delaytime = m_timer.elapsed();
    qDebug()<<"冒泡排序随机数总共用时:"<<m_delaytime<<"毫秒";
    emit FinishBupple(m_list);
}

MQuick类和MBupple一样,我这里只给出代码:

MQuick::MQuick(QObject *parent) : QThread(parent)
{

}

void MQuick::RecviveNum(QVector<int> rlist)
{
    m_list=rlist;
}

void MQuick::run()
{
    qDebug()<<"快速排序的线程ID号为"<<QThread::currentThread();
    QElapsedTimer m_timer;
    m_timer.start();
    int temp;
    quickSort(m_list,0,m_list.size()-1);
    int m_delaytime = m_timer.elapsed();
    qDebug()<<"快速排序随机数总共用时:"<<m_delaytime<<"毫秒";
    emit FinishQuick(m_list);
}

void MQuick::quickSort(QVector<int> &s,int l,int r){
    if(l<r){
        int i=l,j=r;
        int x=s[l];
        while(i<j){
            while(i<j&&s[j]>=x){
                j--;
            }
            if(i<j){
                s[i++]=s[j];
            }

            while(i<j&&s[i]<x){
                i++;
            }
            if(i<j){
                s[j--]=s[i];
            }
        }
        s[i]=x;
        quickSort(s,l,i-1);
        quickSort(s,i+1,r);
    }
}

然后是主线程,主线程主要负责显示生成的随机数以及排序的结果
在这里插入图片描述
这里给出代码:
cpp:

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    gen=new Generate;
    mbu=new MBupple;
    mqu=new MQuick;
    connect(this,&Widget::SendNum,gen,&Generate::RecviveNum);
    connect(gen,&Generate::SendArray,this,&Widget::ReceiveArray);
    connect(gen,&Generate::SendArray,mbu,&MBupple::RecviveNum);
    connect(gen,&Generate::SendArray,mqu,&MQuick::RecviveNum);
    connect(mbu,&MBupple::FinishBupple,this,&Widget::ReceiveBuppleArray);
    connect(mqu,&MQuick::FinishQuick,this,&Widget::ReceiveQuickArray);
}

Widget::~Widget()
{
    delete ui;
    if(gen!=nullptr){
        delete gen;
        gen=nullptr;
    }
    if(mbu!=nullptr){
        delete mbu;
        mbu=nullptr;
    }

    if(mqu!=nullptr){
        delete mqu;
        mqu=nullptr;
    }
  
}

void Widget::ReceiveArray(QVector<int> randlist)
{
    m_receivelist=randlist;
    for(int i=0;i<m_receivelist.size();i++){
        ui->Randomlist->addItem(QString::number(m_receivelist.at(i)));
    }
    //启动排序线程
    mbu->start();
    mqu->start();
}

void Widget::ReceiveBuppleArray(QVector<int> randlist)
{
    m_receivelist=randlist;
    for(int i=0;i<m_receivelist.size();i++){
        ui->Bubblelist->addItem(QString::number(m_receivelist.at(i)));
    }
}

void Widget::ReceiveQuickArray(QVector<int> randlist)
{
    m_receivelist=randlist;
    for(int i=0;i<m_receivelist.size();i++){
        ui->Quicklist->addItem(QString::number(m_receivelist.at(i)));
    }
}

void Widget::on_btnstart_clicked()
{
    emit SendNum(10000);
    gen->start();
}

.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QVector>
#include "mythread.h"
#pragma execution_character_set("utf-8")
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
signals:
    //向子线程发送生成随机数个数
    void SendNum(int num);
    //发送随机数给冒泡 快速线程
    void SendList(QVector<int> list);
private:
    Ui::Widget *ui;
    QVector<int> m_receivelist;
    Generate* gen=nullptr;
    MBupple* mbu=nullptr;
    MQuick* mqu=nullptr;
public slots:
    //接收子线程随机数
    void ReceiveArray(QVector<int> randlist);

    void ReceiveBuppleArray(QVector<int> randlist);
    void ReceiveQuickArray(QVector<int> randlist);

private slots:
    void on_btnstart_clicked();
};
#endif // WIDGET_H

记得在main.cpp里注册类型,不然传递数据有问题,主要是为了支持信号与槽的机制,方便元对象处理跨线程的数据以及跨dll的数据,保证数据的可靠安全,准确判断数据的类型。

#include "widget.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    qRegisterMetaType<QVector<int>>("QVector<int>");
    Widget w;
    w.show();
    return a.exec();
}

这下可以看到三个线程有不同的id号地址,也可以比较出排序的速度
在这里插入图片描述
可能中间这种不停地用信号与槽机制传递数据比较混乱一点,但是仔细捋捋还是能搞懂,另外可以考虑单例模式来实现这种繁琐的数据传递应该更好一点。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习 | Python实现NARX模型预测控制

机器学习 | Python实现NARX模型预测控制 目录 机器学习 | Python实现NARX模型预测控制效果一览基本介绍研究内容程序设计参考资料效果一览 基本介绍 机器学习 | Python实现NARX模型预测控制 研究内容 贝叶斯黑盒模型预测控制,基于具有外源输入的非线性自回归模型的预期自由能最…

后端通过CorsRegistry对象配置了全局跨域,但是前端仍然报CORS跨域错误

后端通过CorsRegistry配置了全局跨域&#xff0c;但是前端仍然报CORS跨域错误 问题背景 在实现登录功能时&#xff0c;我先是通过CorsRegistry配置了全局跨域&#xff0c;然后配置了一个登录拦截器后前端就报错CORS跨域错误 问题原因 前置知识 首先我们来了解一下什么是跨域错误…

hw技战法整理参考

目录 IP溯源反制 账户安全策略及预警 蜜罐部署联动方案

【42万字,2902页】全网最全《零基础网络安全/黑客自学笔记》,爆肝分享!

这次为大家带来一份零基础也能学会的《全网最全黑客自学笔记》&#xff0c;“全网最全”可不是吹牛的&#xff0c;整个笔记一共42万字&#xff0c;2902页&#xff0c;95个章节。 这份笔记涵盖了网络安全导论、渗透测试基础、网络基础、Linux操作系统基础、web安全等等入门知识…

基于应用值迭代的马尔可夫决策过程(MDP)的策略的机器人研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

【SSM】问题集锦(持续更新)

目录 1.错误500&#xff1a;Servlet.init() for servlet DispatcherServlet threw exception Error creating bean with name ‘sqlSessionFactory’ defined in class path reso 主要解决方法可参考这篇文章 我自己的问题是因为spring上下文应用程序关联问题 2.org.apache.c…

带你了解什么是XxxxMapper.xml-SQL 映射文件

文章目录 XxxxMapper.xml-SQL 映射文件官方文档XxxMapper.xml-基本介绍SQL 映射文件常用的几个顶级元素&#xff08;按照应被定义的顺序列出&#xff09;&#xff1a; XxxMapper.xml-详细说明新建Module xml-mapper代码准备基本使用parameterType(输入参数类型)parameterType(输…

新产品:Stimulsoft Forms 2023.3.1 Crack

Stimulsoft Forms 是一个用于交互式收集和处理用户数据的组件。表单工具可以轻松集成到您的项目或应用程序中&#xff0c;具有直观且用户友好的界面&#xff0c;并允许您创建丰富的表单模板。Stimulsoft Forms 是应用程序中与用户交互的新水平 什么是 Stimulsoft Forms&#xf…

[JAVAee]文件操作-IO

本文章讲述了通过java对文件进行IO操作 IO:input/output,输入/输出. 建议配合文章末尾实例食用 目录 文件 文件的管理 文件的路径 文件的分类 文件系统的操作 File类的构造方法 File的常用方法 文件内容的读写 FileInputStream读取文件 构造方法 常用方法 Scan…

VLAN原理(Virtual LAN 虚拟局域网)

VLAN&#xff08;Virtual LAN 虚拟局域网&#xff09; 1、广播/广播域 2、广播的危害&#xff1a;增加网络/终端负担&#xff0c;传播病毒&#xff0c; 3、如何控制广播&#xff1f;&#xff1f; ​ 控制广播隔离广播域 ​ 路由器物理隔离广播 ​ 路由器隔离广播缺点&…

BLE配对和绑定

参考&#xff1a;一篇文章带你解读蓝牙配对绑定 参考&#xff1a;BLE安全之SM剖析(1) 参考&#xff1a;BLE安全之SM剖析&#xff08;2&#xff09; 参考&#xff1a;BLE安全之SM剖析(3) 目录 前言基本概念解读Paring(配对)Bonding(绑定&#xff09;STK短期秘钥、LTK长期秘钥等 …

通过案例实战详解elasticsearch自定义打分function_score的使用

前言 elasticsearch给我们提供了很强大的搜索功能&#xff0c;但是有时候仅仅只用相关度打分是不够的&#xff0c;所以elasticsearch给我们提供了自定义打分函数function_score&#xff0c;本文结合简单案例详解function_score的使用方法&#xff0c;关于function-score-query…

const对象不能调用其他非const成员函数,const成员函数不能调用其他非const成员,

在C语言中我们知道const关键字修饰的变量具有常量属性&#xff0c;简称常变量。即修饰后的变量不能再次修改&#xff0c;而C中是兼容C语言的&#xff0c;同样具备该特性&#xff0c;但C引入了引用&#xff08;&&#xff09;所以const的用法就更多了。 我们知道引用的对象必…

rust 闭包函数

函数有自己的类型&#xff0c;可以像使用基础类型一样使用函数&#xff0c;包括将函数保存在变量中、保存在 vec 中、声明在结构体成员字段中。闭包函数也是函数&#xff0c;也有自己的类型定义。不过&#xff0c;函数实际上是指针类型&#xff0c;在 rust 所有权中属于借用的关…

主从搭建失败的原因

1、Slave_IO_Running是connecting&#xff0c;Slave_SQL_Running是yes 是因为从机使用配置的主机信息没有登陆到主机里面&#xff01;修改(从机里面) 2、Slave_IO_Running是yes&#xff0c;Slave_SQL_Running是no 原因是主机和从机里的数据不一致&#xff1a; 导致&#xff…

轮趣科技教育版ros小车键盘控制运动

我之前买的ros小车是单独买的底板&#xff0c;以为随便一个树莓派就可以&#xff0c;因为我以前有一个树莓派3B&#xff0c;后来买了单独的小车之后&#xff0c;发现只能使用树莓派4B&#xff0c;然后又单独买了一个树莓派4B&#xff0c;给装上镜像&#xff0c;安装ros-melodic…

容斥原理 训练笔记

​ 容斥原理 设S是一个有限集&#xff0c;A_1,A_2…A_n是S的n个子集&#xff0c;则 ∣ S − ⋃ i 1 n A i ∣ ∑ i 0 n ( − 1 ) i ∑ 1 ≤ j 1 < j 2 . . . < j i ≤ n ∣ ⋂ k 1 i A j k ∣ |S-\bigcup_{i1}^{n}A_i|\sum_{i0}^{n}(-1)^i\sum_{1\leq j_1< j_2.…

简单说说SAP系统中BASIS这个Package

1. 简介 BASIS是SAP系统中非常基础的一个包&#xff0c;属于SAP_BASIS这个模块&#xff0c;这个模块其实也代表着SAP Netweaver的版本&#xff0c;通常而言&#xff0c;SAP_BASIS的版本越高&#xff0c;其所支持的功能也越丰富&#xff0c;例如功能更丰富的ABAP语法&#xff0…

UE4 unlua学习笔记

将这三个插件放入Plugins内并重新编译 创建一个BlueprintLibrary&#xff0c;声明一个全局函数 在这里声明路径 点击Create Lua Template 在Content的Script即可生成对应的lua文件打开它&#xff01; 显示以上lua代码 打印Hello Unlua 创建该UI&#xff0c;就会在创建UI的Con…

数值分析第五章节 用Python实现解线性方程组的直接解法

参考书籍&#xff1a;数值分析 第五版 李庆杨 王能超 易大义编 第5章 解线性方程组的直接解法 文章声明&#xff1a;如有发现错误&#xff0c;欢迎批评指正 文章目录 引言与预备知识高斯消去法列主元消去法 矩阵三角分解法杜利特尔分解法平方根法 向量和矩阵的范数误差分析 引言…