Qt 初学子线程实例1 - - 随机数排序

一、 线程类 QThread

方法1:

             (1)需要创建一个线程类的子类,让其继承QT中的线程类 QThread。

             (2)重写父类的 run() 方法,在该函数内部编写子线程,要处理的具体的任务,并通过信号函数,把完成的结果发生到主线程。

             (3)在主线程中,创建子线程对象,通过new方式创建,注意不用写(this)。

             (4)通过主线程的信号(按钮点击),启动子线程, 调用 start() 方法。

             (5)当子线程创建出来之后,主线程与子线程之间的通信可以通过信号槽的方式,通过主线程的信号函数,传递子线程需要的数据(产生随机数的数量)。

             (6)此时,子线程会执行run()函数完成具体任务(生成一定数量的随机数)。

             (7)通过信号槽方式,在主线程显示,接受的子线程发送的随机数结果。(显示界面只能在主线程操作,子线程不能直接操作)

              (8)运行完成,释放线程资源。

示例代码

1.子线程 生成 随机数,通过 重写子线程虚函数,用来生成随机数、放置随机数、并发送到主线程

        1.1 编写生成 随机数的类(头文件、源文件)        

        1.2 重写 子线程虚函数,用来生成随机数,然后,QVector<int> list 放置随机数 数组

        1.3 触发 信号函数 发送子线程生成的随机数

//头文件
#include <QThread>  //线程类头文件
#include <QVector>  //动态数组容器类

//1.生产随机数
class Generate : public QThread
{
    Q_OBJECT
public:
    explicit Generate(QObject *parent = nullptr);
    void recvNum(int num); //接收 外部需要产生随机数的数量num, 传递给m_num
    
//2.重写子线程虚函数
protected:
    void run() override;
signals:
//3.触发 信号函数 发送子线程生成的随机数 数组
    void sendArray(QVector<int> num); 
    
private:
    int m_num; //产生随机数 数量
    
};
//源文件
#include "mythread.h"
#include <QElapsedTimer>  //计时工具,用于测量代码执行时间和延迟时间
#include <QDebug>

Generate::Generate(QObject *parent) : QThread(parent)
{
    
}

void Generate::recvNum(int num) //接收 外部需要产生随机数的数量num, 传递给m_num
{
    m_num = num;
}

void Generate::run()  //重写虚函数 子线程生成的随机数数组发生给主线程
{
    qDebug()<<"生成随机数ID"<<QThread::currentThread(); //获取当前执行线程的ID
    QVector<int> list;  //创建一个数组,放置随机数
    QElapsedTimer time; //创建一个time,记录生成m_num个随机数 代码执行的时间
    time.start();    //启动计时器

    for(int i = 0; i < m_num; ++i)
    {
        //qrand() %100000  生成100000以内的随机数
        list.push_back(qrand() %100000);  //push_back 在数组末尾添加一个元素
        
    }

    int milsec = time.elapsed();//代码执行的时间  ms  
    qDebug()<<"生成"<<m_num<<"随机数总共耗时:"<<milsec<<"ms";
    
    //触发 发送生成的随机数数组 到主线程
    emit sendArray(list);
    
}

2. 主线程 

        2.1 创建子线程对象

        2.2 主线程 将 需要生成的随机数 数量 传递给子线程对象的槽函数 

        2.3 启动子线程 ,子线程会执行run()函数完成具体任务(生成一定数量的随机数)

        2.4 通过信号槽函数  ,主线程 接受 子线程发送的随机数数组 显示出来

//头文件
#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
signals:
    void starting(int num);

private:
    Ui::Widget *ui;
};
//源文件
#include "widget.h"
#include "ui_widget.h"
#include "mythread.h"

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

    //1.创建子线程对象
    Generate *gen = new Generate;

    //主线程 将 需要生成的随机数数量 传递给子线程对象的槽函数
    connect(this,&Widget::starting,gen,&Generate::recvNum);

    //2.启动子线程
    connect(ui->start,&QPushButton::clicked,this,[=]()
    {
        emit starting(10000); //主线程需要生成 10000个随机数传递出去
        gen->start();
    });

    //3.接受 子线程发送的随机数 在主线程 打印出来
    connect(gen,&Generate::sendArray,this,[=](QVector<int> list)
    {
        for(int i=0; i<list.size(); ++i)
        {
            ui->randList->addItem(QString::number(list.at(i)));  //将数字转换为QString类型
        }
    });


}

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

3. 子线程 冒泡排序(快速排序与冒泡排序类似),  重复上述1-2步骤,:

        3.1 通过重写 子线程虚函数run,用来对随机数数组进行 ,并将排序结果,通过 emit 发送到主线程。 

//头文件
//1.冒泡排序
class BubbleSort : public QThread
{
    Q_OBJECT
public:
    explicit BubbleSort(QObject *parent = nullptr);
    void recvArray(QVector<int> list);

//2.重写子线程虚函数
protected:
    void run() override;
signals:
//3.触发 信号函数 发送子线程生成的冒泡排序数组 到主线程
    void finish(QVector<int> num);
private:
//需要排序的对象
    QVector<int> m_list;
};
//源文件
void BubbleSort::run()
{
    // 日志的 输出
    qDebug() << "  冒泡排序的线程的线程地址: " << QThread::currentThread();

    QElapsedTimer time;
    time.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 milsec = time.elapsed(); //程序段,流程执行完毕的时间,单位毫秒
    qDebug() << "冒泡排序" <<  milsec << "毫秒";

    //触发 发送生成的冒泡排序数组 到主线程
    emit finish(m_list);
}

        3.2 在主线程中,创建子线程对象,启动子线程(在子线程生成随机数之后), 通过信号槽函数,随机数对象信号函数(发送随机数数组),冒泡排序对象接收随机数数组。

        3.3 通过信号槽函数  ,主线程 接受 子线程发送的冒泡排序结果 显示出来 。         

//1.创建子线程对象  
BubbleSort* bubble =new BubbleSort;
QuickSort* quick =new QuickSort;

//3.接收来自gen.sendArray 传来的数组,到冒泡排序类
connect(gen,&Generate::sendArray,bubble,&BubbleSort::recvArray);
//3.接收来自gen.sendArray 传来的数组,到快速排序类
connect(gen,&Generate::sendArray,quick,&QuickSort::recvArray);

//2.接受 子线程发送的随机数 在主线程 打印出来
connect(gen,&Generate::sendArray,this,[=](QVector<int> list)
{
   //此时,随机数数组已经生成完毕,启动,bubble、quick子线程
   bubble->start();
   quick->start();

   for(int i=0; i<list.size(); ++i)
    {
      ui->randList->addItem(QString::number(list.at(i)));  //将数字转换为QString类型
    }
});


//4.接收数组,进行冒泡排序,并显示在框内
connect(bubble,&BubbleSort::finish,this,[=](QVector<int> list)
{
    for (int i = 0;i<list.size() ; ++i )
     {
        ui->bubbleList->addItem(QString::number(list.at(i)));
     }
});

//7.接收数组,进行快速排序,并显示在框内
connect(quick,&QuickSort::finish,this,[=](QVector<int> list)
{
     for (int i = 0;i<list.size() ; ++i )
     {
        ui->quickList->addItem(QString::number(list.at(i)));
     }
});

   

          3.4 线程资源释放。 

    //8.线程资源释放
    connect(this,&Widget::destroyed,this,[=]()
    {
        gen->quit();
        gen->wait();
        gen->deleteLater(); //delete t1

        bubble->quit();
        bubble->wait();
        bubble->deleteLater();

        quick->quit();
        quick->wait();
        quick->deleteLater();

    });

 快速排序代码段:

//快速排序
void quickSort(QVector<int> &s,int l,int r)
{
    if(l >= r) return;

    int i=l-1,j=r+1,x=s[l + r >> 1];
    while(i<j)
    {
        do i++;while(s[i]<x);
        do j--;while(s[j]>x);
        if(i<j)
        {
            int temp = s[i];
                s[i] = s[j];
                s[j] = temp;
        }
    }

    quickSort(s,l,j);
    quickSort(s,j+1,r);

}

参考资料

1.Qt中多线程的使用 | 爱编程的大丙

2.容器类:QVector、QList、QSet、QMap使用_qvector添加元素-CSDN博客

3.QElapsedTimer-CSDN博客

4.Qt中多线程-线程池的使用-C/C++/qt_哔哩哔哩_bilibili

  • 25
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值