自学内容网 自学内容网

QT中多线程的使用(一)

参考资料

https://subingwen.cn/qt/thread/#1-%E7%BA%BF%E7%A8%8B%E7%B1%BB-QThread
https://www.bilibili.com/video/BV1iN411f7dY?buvid=XU932919AEC08339E30CE57D39A2BABF6A44F&from_spmid=search.search-result.0.0&is_story_h5=false&mid=rSmqqQLB5PQj7nof4wjfpQ%3D%3D&plat_id=114&share_from=ugc&share_medium=android&share_plat=android&share_session_id=a01714b7-a97c-4ec7-8dbb-548099f05c05&share_source=WEIXIN&share_source=weixin&share_tag=s_i&spmid=united.player-video-detail.0.0&timestamp=1737024828&unique_k=gr9tHaA&up_id=147020887&vd_source=b3723521e243814388688d813c9d475f&spm_id_from=333.788.player.switch&p=7

1.使用方式
在Qt中使用多线程来处理比较复杂的逻辑时,可以将这个逻辑写到一个类中。这个类继承QThread类,并且重写其中的run()方法,当调用start()方法的时候,run()方法会被自动调用。

假设现在要生成10000个随机数,如果在主线程中直接生成,那么主界面会非常的卡顿,此时需要重新创建一个子线程。

#pragma once
#include <QThread>
class Generate:public QThread
{
    Q_OBJECT
public:
    explicit Generate(QObject* parent = nullptr);
    void recvNum(int num);
    void setNum(int num);
protected:
    //重写QThread类中的run方法
    void run()override;
signals:
    void sendArray(QVector<int> num);
private:
    int m_num;
};


#include "Generate.h"
#include <QDebug>
#include <QVector>
#include <QElapsedTimer>
#include <QRandomGenerator>

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

void Generate::recvNum(int num)
{
    m_num = num;
}

void Generate::setNum(int num)
{
    m_num = num;
}

void Generate::run()
{
    //生成m_num个随机数
    qDebug() << "生成随机数的线程的线程地址是:" << QThread::currentThread();
    QVector<int> list;
    //list.resize(m_num);
    //统计生成这些随机数所消耗的时间
    QElapsedTimer time;
    time.start();
    for (int i = 0; i < m_num; i++)
    {
        list.push_back(QRandomGenerator::global()->bounded(10000));
    }
    int milsec = time.elapsed();
    qDebug() << "生成" << m_num << "个随机数总共耗时" << QString::number(milsec);
    //生成完随即数后发送信号告诉主线程可以使用这些数据了
    emit sendArray(list);
}

当主线程需要使用的时候,可以通过run()方法来调用这个类的处理逻辑。在主线程中的使用方式如下:
在这里插入图片描述
2.例子:使用多线程实现对10000个数据的排序,并通过冒泡排序和快速排序分别对二者进行排序,得到的结果显示在界面上。
主界面代码:

#pragma once
#include <QPushButton>
#include <QWidget>
#include <QListWidget>
#include <QVBoxLayout>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QWidget>
#include <QMainWindow>

//创建程序所需要的界面
class Ui_QThread1Page {
public:
    //界面所需要的组件
    QGroupBox* groupBox;
    QGroupBox* groupBox_2;
    QGroupBox* groupBox_3;
    QListWidget* randList;
    QListWidget* bubbleList;
    QListWidget* quickList;

    QHBoxLayout* hboxLayout4;
    QPushButton* btnStart;
    QVBoxLayout* vboxLayout;

    QVBoxLayout* vboxLayout1;
    QVBoxLayout* vboxLayout2;
    QVBoxLayout* vboxLayout3;

public:
    void setupUi(QWidget* parent)
    {
        groupBox = new QGroupBox;
        groupBox_2 = new QGroupBox;
        groupBox_3 = new QGroupBox;

        groupBox->setTitle("randList");
        groupBox_2->setTitle("bubbleList");
        groupBox_3->setTitle("quickList");

        randList = new QListWidget;
        bubbleList = new QListWidget;
        quickList = new QListWidget;

        hboxLayout4 = new QHBoxLayout;

        btnStart = new QPushButton;
        btnStart->setText("btnStart");
        vboxLayout = new QVBoxLayout;

        vboxLayout1 = new QVBoxLayout;
        vboxLayout2 = new QVBoxLayout;
        vboxLayout3 = new QVBoxLayout;

        vboxLayout1->addWidget(randList);
        groupBox->setLayout(vboxLayout1);

        vboxLayout2->addWidget(bubbleList);
        groupBox_2->setLayout(vboxLayout2);

        vboxLayout3->addWidget(quickList);
        groupBox_3->setLayout(vboxLayout3);

        hboxLayout4->addWidget(groupBox);
        hboxLayout4->addWidget(groupBox_2);
        hboxLayout4->addWidget(groupBox_3);

        vboxLayout->addLayout(hboxLayout4);
        vboxLayout->addWidget(btnStart);
        parent->setLayout(vboxLayout);
        parent->setFixedSize(800,600);
    }
};

namespace Ui {
    class QThread1Page :public Ui_QThread1Page {};
}
#pragma once

#include <QtWidgets/QWidget>
#include <QMainWindow>
#include "ui_QThread1.h"

class QThread1 : public QWidget
{
    Q_OBJECT

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

private:
    Ui::QThread1Page *ui_;
};

#include "QThread1.h"
#include "Generate.h"
#include "BubbleSort.h"
#include "QuickSort.h"
#include <QString>
#include <QDebug>

QThread1::QThread1(QWidget *parent)
    : QWidget(parent)
    , ui_(new Ui::QThread1Page)
{
    //1.初始化显示界面
    ui_->setupUi(this);
    //2.创建对应的子线程类
    Generate* gen = new Generate;//生成随机数
    BubbleSort* bubble = new BubbleSort;//冒泡排序
    QuickSort* quick = new QuickSort;//快速排序

    /*
    * 因为上述的三个子类都继承了QThread类,并且重写了run()方法
    * 所以调用对应对象的btnStart方法时,run中的函数会在子线程中运行
    */
    //3.主线程的逻辑
    //connect(this, &QThread1::starting, gen, &Generate::recvNum);

    connect(ui_->btnStart, &QPushButton::clicked, this, [=]() 
    {
            gen->setNum(1000000);
            //emit starting(100000);
            gen->start();
    });

    //两个子线程接收数据
    connect(gen, &Generate::sendArray, bubble, & BubbleSort::recvArray);
    connect(gen, &Generate::sendArray, quick, &QuickSort::recvArray);

    //主线程开始显示数据,并且启动子线程的排序功能
    connect(gen, &Generate::sendArray, this, [=](QVector<int> list)->void 
    {
        for (int i = 0; i < list.size(); i++) 
        {
            ui_->randList->addItem(QString::number(list.at(i)));
        }
    });
    connect(gen, &Generate::sendArray, this, [=](QVector<int> list)->void
        {
            bubble->start();
            quick->start();
        });

    //当子线程排序完数据后,在主线程中显示数据
    connect(bubble, &BubbleSort::finish, this, [=](QVector<int>list) 
    {
        for (int i = 0; i < list.size(); i++)
        {
           ui_->bubbleList->addItem(QString::number(list.at(i)));
        }
    });
    connect(quick, &QuickSort::finish, this, [=](QVector<int>list)
    {
        for (int i = 0; i < list.size(); i++)
        {
            ui_->quickList->addItem(QString::number(list.at(i)));
        }
    });

    connect(this, &QThread1::close, this, [=]()
    {
        gen->quit();
        gen->wait();
        gen->deleteLater();//相当于delete gen

        bubble->quit();
        bubble->wait();
        bubble->deleteLater();//相当于delete bubble

        quick->quit();
        quick->wait();
        quick->deleteLater();//相当于delete quick
        qDebug() << "process quit...";
    });

}

QThread1::~QThread1()
{}

#pragma once
#include <QThread>
#include <QVector>
class BubbleSort : public QThread
{
    Q_OBJECT
public:
    explicit BubbleSort(QObject* parent = nullptr);

    void recvArray(QVector<int> list);
protected:
    virtual void run()override;
signals:
    void finish(QVector<int> list);
private:
    QVector<int> m_list;
};


#include "BubbleSort.h"
#include <QDebug>
#include <QElapsedTimer>

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

}

void BubbleSort::recvArray(QVector<int> list)
{
    m_list = list;
}

void BubbleSort::run()
{
    qDebug() << "bubble sort thread address is:" << 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() << "bubble sort time is " << milsec << "ms";
    emit finish(m_list);
}

#pragma once
#include <QThread>
#include <QVector>
class QuickSort : public QThread
{
    Q_OBJECT
public:
    explicit QuickSort(QObject* parent = nullptr);

    void recvArray(QVector<int> list);
private:
    void quickSort(QVector<int>& list, int l, int r);
protected:
    virtual void run()override;
signals:
    void finish(QVector<int> list);
private:
    QVector<int> m_list;
};




#include "QuickSort.h"
#include <QDebug>
#include <QElapsedTimer>

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

}

void QuickSort::recvArray(QVector<int> list)
{
    m_list = list;
}

void QuickSort::run()
{
    qDebug() << "quick sort thread address is :" << QThread::currentThread();
    QElapsedTimer time;
    time.start();
    quickSort(m_list, 0, m_list.size() - 1);
    int milsec = time.elapsed();
    qDebug() << "quick sort time is" << milsec << "ms";
    emit finish(m_list);
}

void QuickSort::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);
    }
}
#include "QThread1.h"
#include <QtWidgets/QApplication>
#include <QApplication>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    qRegisterMetaType<QVector<int>>("QVector<int>");
    QThread1 w;
    w.show();
    return a.exec();
}


原文地址:https://blog.csdn.net/weixin_40933496/article/details/145229434

免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!