QT多线程的示例

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

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

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

相关文章

联想拯救者笔记本切换独显直连游戏体验翻倍、火力全开“嗨”起来

最早的游戏本是由独显负责图形运算&#xff0c;然后直接向屏幕输出所有画面的。但独显负责所有工作&#xff0c;无时无刻都在耗电&#xff1b;撇开游戏模式下高负载的功耗不谈&#xff0c;即便在省电模式下功耗也比核显高得多。 英伟达发布的Optimus混合输出技术&#xff0c;在…

Python入门【变量的作用域(全局变量和局部变量)、参数的传递、浅拷贝和深拷贝、参数的几种类型 】(十一)

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱敲代码的小王&#xff0c;CSDN博客博主,Python小白 &#x1f4d5;系列专栏&#xff1a;python入门到实战、Python爬虫开发、Python办公自动化、Python数据分析、Python前后端开发 &#x1f4e7;如果文章知识点有错误…

【深度学习】【三维重建】windows10环境配置PyTorch3d详细教程

【深度学习】【三维重建】windows10环境配置PyTorch3d详细教程 文章目录 【深度学习】【三维重建】windows10环境配置PyTorch3d详细教程前言确定版本对应关系源码编译安装Pytorch3d总结 前言 本人windows10下使用【Code for Neural Reflectance Surfaces (NeRS)】算法时需要搭…

python 网络编程

TCP编程 客户端 创建TCP连接时&#xff0c;主动发起连接的叫做客户端&#xff0c;被动响应的叫做服务端。当定义一个Socket表示打开一个网络连接&#xff0c;创建一个Socket需要知道目标计算机的IP地址和端口号和对应的协议类型。 # 导入socket库: import socket# 创建一个s…

深度剖析C++ 异常机制

传统排错 我们早在 C 程序里面传统的错误处理手段有&#xff1a; 终止程序&#xff0c;如 assert&#xff1b;缺陷是用户难以接受&#xff0c;说白了就是一种及其粗暴的手法&#xff0c;比如发生内存错误&#xff0c;除0错误时就会终止程序。 返回错误码。缺陷是需要我们自己…

网络安全/信息安全—学习笔记

一、网络安全是什么 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 无论网络、Web、移动、桌面、云等哪个领域&#xff0c;都有攻与防两面…

golang文件锁,目录锁,syscall包的使用

先说结论 1. golang提供了syscall包来实现文件/目录的加锁&#xff0c;解锁 2. syscall包属于文件锁&#xff0c;是比较底层的技术&#xff0c;并不能在所有操作系统上完全实现&#xff0c;linux上实现了&#xff0c;windows下面就没有 3. 加锁时调用syscall.Flock(fd&#…

2023 年还推荐报计算机专业吗?

计算机科学是一个很好的专业&#xff0c;因为它由各种课程组成&#xff0c;为学生在成熟和新兴专业就业做好准备。以下是一些通常属于计算机科学专业的课程&#xff1a; 基本编程介绍了用于构建和维护数字架构和基础设施的编程语言和标准。 微积分为制定高级计算和设计概念提供…

mac不识别移动硬盘导致无法拷贝资源

背景 硬盘插入到Mac电脑上之后&#xff0c;mac不识别移动硬盘导致无法拷贝资源。 移动硬盘在Mac上无法被识别的原因可能有很多&#xff0c;多数情况下&#xff0c;是硬盘的格式与Mac电脑不兼容。 文件系统格式不兼容 macOS使用的文件系统是HFS或APFS&#xff0c;如果移动硬盘是…

C# 关于使用newlife包将webapi接口寄宿于一个控制台程序、winform程序、wpf程序运行

C# 关于使用newlife包将webapi接口寄宿于一个控制台程序、winform程序、wpf程序运行 安装newlife包 Program的Main()函数源码 using ConsoleApp3; using NewLife.Log;var server new NewLife.Http.HttpServer {Port 8080,Log XTrace.Log,SessionLog XTrace.Log }; serv…

OpenLayers入门,OpenLayers鼠标移动事件使用,实现鼠标移动到点位上方后高亮显示点位要素

专栏目录: OpenLayers入门教程汇总目录 前言 本章主要讲解OpenLayers鼠标移动事件的使用,并简单实现鼠标移动到点位上方后高亮显示点位要素的功能,带领大家快速上手OpenLayers鼠标移动事件的应用。 二、依赖和使用 "ol": "^6.15.1"使用npm安装依赖…

nlp系列(6)文本实体识别(Bi-LSTM+CRF)pytorch

模型介绍 LSTM&#xff1a;长短期记忆网络&#xff08;Long-short-term-memory&#xff09;,能够记住长句子的前后信息&#xff0c;解决了RNN的问题&#xff08;时间间隔较大时&#xff0c;网络对前面的信息会遗忘&#xff0c;从而出现梯度消失问题&#xff0c;会形成长期依赖…

JavaEE简单示例——在使用Tomcat的时候可能出现的一些报错

简单介绍&#xff1a; 在我们之前使用Tomcat的时候&#xff0c;经常会出现在启动的时候因为一些报错导致项目无法正常的启动&#xff0c;我们就对一些比较常见的报错来看一下可能导致的原因&#xff0c;以及出现报错之后如何去解决。 严重: Failed to initialize end point a…

Flutter 添加 example流程

一、已有Flutter工程&#xff08;命令&#xff09;添加 example 1、cd 工程(flutter_plugin ,是自己创建的)根目录 例: flutter create example 执行命令创建example PS&#xff1a;cd example 后执行flutter doctor 后就可以看到效果 2、如果需要指定iOS/Android 语言,请添加…

[Python] flask运行+wsgi切换生产环境+supervisor配置指南

文章目录 问题背景flask启动方式1&#xff08;编写main函数&#xff09;&#xff1a;方式2&#xff08;编译器&#xff09;&#xff1a;方式3&#xff08;命令行&#xff09;&#xff1a;方法4&#xff08;重命名文件法&#xff09;&#xff1a;方法5&#xff08;使用flask命令…

【C++ 进阶】第 1 章:[C 语言基础] C 语言概述与数据类型

目录 一、C 语言的概述 &#xff08;1&#xff09;计算机结构组成 &#xff08;2&#xff09;计算机系统组成 &#xff08;3&#xff09;ASCII 码 &#xff08;4&#xff09;计算机中的数制及其转换 &#xff08;5&#xff09;程序与指令 &#xff08;6&#xff09;语…

菜鸡shader:L13 渐隐渐显的UV动画

文章目录 SD部分Shader代码部分 呃呃&#xff0c;这是目前我学习庄懂AP01课程的最后一节了&#xff0c;我看了一下21集之后的内容是关于LightingMap&#xff0c;目前感觉还用不到&#xff0c;加上之前参与过一个项目里面也有用到LightingMap&#xff0c;也算了解过&#xff0c;…

【深度学习】【Image Inpainting】Generative Image Inpainting with Contextual Attention

Generative Image Inpainting with Contextual Attention DeepFillv1 (CVPR’2018) 论文&#xff1a;https://arxiv.org/abs/1801.07892 论文代码&#xff1a;https://github.com/JiahuiYu/generative_inpainting 论文摘录 文章目录 效果一览摘要介绍论文贡献相关工作Image…

Unity XML1——XML基本语法

一、XML 概述 ​ 全称&#xff1a;可拓展标记语言&#xff08;EXtensible Markup Language&#xff09; ​ XML 是国际通用的&#xff0c;它是被设计来用于传输和存储数据的一种文本特殊格式&#xff0c;文件后缀一般为 .xml ​ 我们在游戏中可以把游戏数据按照 XML 的格式标…

23款奔驰GLS450加装原厂香氛负离子系统,清香宜人,久闻不腻

奔驰原厂香氛合理性可通过车内空气调节组件营造芳香四溢的怡人氛围。通过更换手套箱内香氛喷雾发生器所用的香水瓶&#xff0c;可轻松选择其他香氛。香氛的浓度和持续时间可调。淡雅的香氛缓缓喷出&#xff0c;并且在关闭后能够立刻散去。车内气味不会永久改变&#xff0c;香氛…