QT多线程

QT多线程


前言

默认情况下,QT只存在一个主线程,而且跟窗口有关的操作放在主线程中。如果程序中有比较费时的操作需要处理,由于只有一个线程存在,当你试着拖拽界面的时候就会出现卡顿。为了处理复杂的操作,我们必须引入多线程。

一、任务分工

主线程:QT中默认的线程,也叫窗口线程,负责窗口事件处理或者窗口控件数据的更新
子线程:负责后台的业务逻辑处理,子线程中不能对窗口对象做任何操作,这些事情需要交给主线程处理
主线程和子线程之间如果要进行数据的传递,必须使用Qt中的信号槽机制!

二、如何创造

Qt 中提供了一个线程类QThread,通过这个类就可以创建子线程了。
步骤如下:
1、创建一个子类,让其继承 QT 中的线程类 QThread
2、在子类中重写父类的 run () 方法,处理的具体的业务流程都要在run()方法中
3、在主线程中创建子线程对象
4、在主线程中调用 start () 方法启动子线程

三、关键步骤

///创建子线程Generate 
class Generate : public QThread
{
    Q_OBJECT
    ...
   void run() override;
	...
};
//重写run()方法
void Generate::run()
{
	...
}
//在主线程中创建子线程对象
Generate *gen = new Generate;
//在主线程中调用start()方法启动子线程
gen->start();

四、代码

mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
signals:
    void starting(int num);
private:
    Ui::MainWindow *ui;

};

#endif // MAINWINDOW_H
mythread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QThread>
#include<QVector>

class Generate : public QThread
{
    Q_OBJECT
public:
    explicit Generate(QObject *parent = nullptr);
    void recvNum(int num);
protected:
   void run() override;

signals:
   void sendArray(QVector<int> list);
   void spendTime(int);

public slots:
private:
   int m_num;
};

class BubbleSort : public QThread
{
    Q_OBJECT
public:
    explicit BubbleSort(QObject *parent = nullptr);
    void recvArray(QVector<int>list);
protected:
   void run() override;

signals:
   void finish(QVector<int> num);
   void spendTime(int);

public slots:
private:
    QVector<int> m_list;
};

class QuickSort : public QThread
{
    Q_OBJECT
public:
    explicit QuickSort(QObject *parent = nullptr);
    void recvArray(QVector<int> list);
private:
    void quickSort(QVector<int> &list,int s,int e);
protected:
   void run() override;

signals:
   void finish(QVector<int> num);
   void spendTime(int);

public slots:
private:
    QVector<int> m_list;
};

#endif // MYTHREAD_H
main.cpp
#include "mainwindow.h"
#include <QApplication>

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

    return a.exec();
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<mythread.h>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    setWindowTitle("线程_排序比较");
    Generate *gen = new Generate;
    QuickSort *quick = new QuickSort;
    BubbleSort *bubble = new BubbleSort;
    connect(this,&MainWindow::starting,gen,&Generate::recvNum);

    connect(ui->start,&QPushButton::clicked,this,[=]()
    {
        gen->start();
        emit starting(30000);
    });
    connect(gen,&Generate::sendArray,bubble,&BubbleSort::recvArray);
    connect(gen,&Generate::sendArray,quick,&QuickSort::recvArray);
    connect(gen,&Generate::sendArray,this,[=](QVector<int>list)
    {
        bubble->start();
        quick->start();
        for(int i = 0;i<list.size();i++)
        {
            //ui->randList->addItem(QString::number(list.at(i)));
            ui->randList->addItem(QString::number(list.at(i)));
        }



    });
    connect(gen,&Generate::spendTime,this,[=](int time)
    {
          ui->showSome->append("生成这些随机数花费了"+QString::number(time)+"毫秒");
    });
    connect(bubble,&BubbleSort::spendTime,this,[=](int time)
    {
          ui->showSome->append("冒泡排序花费了"+QString::number(time)+"毫秒");
    });
    connect(quick,&QuickSort::spendTime,this,[=](int time)
    {
          ui->showSome->append("快速排序花费了"+QString::number(time)+"毫秒");
    });
    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, &MainWindow::destroy, this, [=]()
    {

        gen->quit();
        gen->wait();
        gen->deleteLater();  // delete t1;

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

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

MainWindow::~MainWindow()
{
    delete ui;
}
mythread.cpp
#include "mythread.h"
#include<QElapsedTimer>
#include <QDebug>
//#include<debug.h>
Generate::Generate(QObject *parent) : QThread(parent)
{

}

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

void Generate::run()
{
    qDebug()<<"生成随机数线程的地址:"<<QThread::currentThread();

    QVector<int> List;
    QElapsedTimer time;
    time.start();
    for(int i = 0;i < m_num;i++)
    {
        List.push_back(qrand() % 100000);

    }
    int millisec = time.elapsed();
   //qDebug()<<"总共花费了"<<millisec<<"毫秒生成了"<<m_num<<"个随机数";
    emit sendArray(List);
    emit spendTime(millisec);

}

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

void BubbleSort::recvArray(QVector<int> list)
{
    m_list = 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 millisec = time.elapsed();
    //qDebug()<<"冒泡排序总共花费了"<<millisec<<"毫秒";
    emit finish(m_list);
    emit spendTime(millisec);
}

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

}

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

void QuickSort::quickSort(QVector<int> &s, int l, int r)
{
    if (l < r)
    {
        int i = l, j = r;
        // 拿出第一个元素, 保存到x中,第一个位置成为一个坑
        int x = s[l];
        while (i < j)
        {
            // 从右向左找小于x的数
            while (i < j && s[j] >= x)
            {
                //左移, 直到遇到小于等于x的数
                j--;
            }
            if (i < j)
            {
                //将右侧找到的小于x的元素放入左侧坑中, 右侧出现一个坑
                //左侧元素索引后移
                s[i++] = s[j];
            }

            // 从左向右找大于等于x的数
            while (i < j && s[i] < x)
            {
                //右移, 直到遇到大于x的数
                i++;
            }
            if (i < j)
            {
                //将左侧找到的元素放入右侧坑中, 左侧出现一个坑
                //右侧元素索引向前移动
                s[j--] = s[i];
            }
        }
        //此时 i=j,将保存在x中的数填入坑中
        s[i] = x;
        quickSort(s, l, i - 1); // 递归调用
        quickSort(s, i + 1, r);
    }
}

void QuickSort::run()
{
    qDebug()<<"快速排序线程的地址:"<<QThread::currentThread();
    QElapsedTimer time;
    time.start();
    quickSort(m_list, 0, m_list.size()-1);
    int millisec = time.elapsed();
    //qDebug()<<"快速排序总共花费了"<<millisec<<"毫秒";
    emit finish(m_list);
    emit spendTime(millisec);
}
mainwindow.ui

QT多线程
参考链接:
https://subingwen.cn/qt/thread/.

上一篇:Go msgp序列化使用详解!比Json更快!面试时吊打面试官!


下一篇:stm32cubeMX生成工程文件