Qt多线程

文章介绍了两种在Qt中实现多线程的方法:一是继承QThread类,创建线程并在run方法中实现任务,通过信号槽进行线程间通信;二是继承QObject,使用moveToThread方法将对象移动到新线程执行任务。通过随机数生成和排序的实例展示了这两种方式的使用,确保任务在不同线程中正确执行。
摘要由CSDN通过智能技术生成

1.qt多线程方法之继承QThread类

       当我们需要使用多线程来执行任务时,我们可以继承QThread类来创建一个线程,在类中重写run方法,在这个run方法中就是我们要执行的任务,如果是需要使用到临界资源,需要使用互斥锁或其他方法来进行线程间的同步,使用start方法来启动线程。此处使用一个排序的例子来说明。

1.生成随机数的线程类-->randThread

class randThread : public QThread
{
    Q_OBJECT
public:
    explicit randThread(QObject *parent = nullptr);
public slots:
    void recv(int num);
protected:
    void run();
signals:
    void sendVector(QVector<int> array);
    void starting();
private:
    int m_num;//生成随机数的数量
};

 ui线程接收这个线程发送的信号。

2.将生成的随机数组进行冒泡排序的排序类-->buddleSort

//进行冒泡排序的类
class buddleSort : public QThread//冒牌排序的线程
{
    Q_OBJECT
public:
    explicit buddleSort(QObject *parent = nullptr);
public slots:
    void recvArray(QVector<int> array);//该方法用来接收ui发送过来的数组
protected:
    void run();//重写run方法
signals:
    void finish(QVector<int> array);
private:
    QVector<int> M_list;
};

ui线程将接收的生成的随机数组发送给这个排序线程

3.ui线程中信号槽函数

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //1.创建子线程
    randThread *rand=new randThread;//生成随机数
    buddleSort *buddle=new buddleSort;//冒泡排序
    //2.启动生成随机数的子线程
    connect(this,&Widget::sendnum,rand,&randThread::recv);//向子线程发送数量
    connect(ui->start,&QPushButton::clicked,this,[=](){
         emit sendnum(10000);
         rand->start();//生成随机数的线程开始启动
    });
    //排序线程接收随机数线程发送过来的随机数组
    connect(rand,&randThread::sendVector,buddle,&buddleSort::recvArray);
    //主线程接收子线程发送过来的随机数组
    connect(rand,&randThread::sendVector,this,[=](QVector<int> array){
        ui->rand->clear();
        for(int i=0;i<array.size();i++){
            ui->rand->addItem(QString::number(array.at(i)));
        }
        buddle->start();//排序线程开始启动
    });
    //当数组排序完成之后,给ui线程发送一个排序完成的信号
    connect(buddle,&buddleSort::finish,this,[=](QVector<int> array){
        ui->buddle->clear();
        foreach(auto str,array){
            ui->buddle->addItem(QString::number(str));
        }
    });
}

2.继承QObject类,使用moveToThread方法

下面是例子:写一个公共的方法,名字随意起,参数也随意设置。

fndef QUICKSORT_H
#define QUICKSORT_H

#include <QObject>
#include <QVector>
#include <QDebug>
#include <QThread>
class quickSort : public QObject
{
    Q_OBJECT
public:
    explicit quickSort(QObject *parent = nullptr);
public slots:
    void  recvArray(QVector<int> list);
    void  working();//这个方法里书写需要执行的任务
signals:
     void sendResult(QVector<int> list);
private:
     QVector<int> Q_list;
};

#endif // QUICKSORT_H

1.继承QObject类

class quickSort : public QObject

2.创建工作对象

quickSort *quick=new quickSort;

3.创建QThread对象

QThread *mythread=new QThread;

4.将该对象移入创建的线程

quick->moveToThread(mythread);

5.启动线程

mythread->start();

6.此时只是线程启动,而真正需要完成任务的那个工作函数并没有启动,我们需要手动开启。

 connect(rand,&randThread::starting,quick,&quickSort::working);/绑定槽函数,启动work方法

这个方法是ui线程发送信号时启动的,也可以手动开启,此时这个方法就会在这个mythread线程里完成。

7.资源回收,使用quit方法与wait方法并删除我们创建的对象

        mythread->quit();
        mythread->wait();
        delete quick;
        delete mythread;

下面是源程序:

1.quicksort.h

#ifndef QUICKSORT_H
#define QUICKSORT_H

#include <QObject>
#include <QVector>
#include <QDebug>
#include <QThread>
class quickSort : public QObject
{
    Q_OBJECT
public:
    explicit quickSort(QObject *parent = nullptr);
public slots:
    void  recvArray(QVector<int> list);
    void  working();
signals:
     void sendResult(QVector<int> list);
private:
     QVector<int> Q_list;
};

#endif // QUICKSORT_H

2.quicksort.cpp

#include "quicksort.h"

quickSort::quickSort(QObject *parent) : QObject(parent)
{

}

void quickSort::recvArray(QVector<int> list)
{
    Q_list=list;
}

void quickSort::working()
{
    qDebug()<<"quickSort thread:"<<QThread::currentThread();
    QVector<int> nums;
    foreach(auto num,Q_list){
        nums.push_front(num);
    }
    emit sendResult(nums);
}

3.randthread.h

#ifndef RANDTHREAD_H
#define RANDTHREAD_H

#include <QObject>
#include <QThread>
#include <QVector>
#include <QDebug>
class randThread : public QThread
{
    Q_OBJECT
public:
    explicit randThread(QObject *parent = nullptr);
public slots:
    void recv(int num);
protected:
    void run();
signals:
    void sendVector(QVector<int> array);
    void starting();
private:
    int m_num;//生成随机数的数量
};

class buddleSort : public QThread
{
    Q_OBJECT
public:
    explicit buddleSort(QObject *parent = nullptr);
public slots:
    void recvArray(QVector<int> array);
protected:
    void run();
signals:
    void finish(QVector<int> array);
private:
    QVector<int> M_list;
};

#endif // RANDTHREAD_H
4.randthread.cpp
#include "randthread.h"

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

}

void randThread::recv(int num)
{
    m_num=num;
}

void randThread::run()
{
    qDebug()<<"rand thread:"<<QThread::currentThread();
    QVector<int> nums;
    for(int i=0;i<m_num;i++){
        nums.push_back(qrand()%100000);
    }
    emit sendVector(nums);
    emit starting();
}

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

}

void buddleSort::recvArray(QVector<int> array)
{
    M_list=array;
}

void buddleSort::run()
{
   qDebug()<<"buddle thread:"<<QThread::currentThread();
   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]){
               int temp=M_list[j];
               M_list[j]=M_list[j+1];
               M_list[j+1]=temp;
           }
       }
   }
   emit finish(M_list);
}

5.widght.h

#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QThread>
#include "randthread.h"
#include "quicksort.h"
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
    void recvarray(QVector<int> arr);
signals:
    void  sendnum(int num);
private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

6.widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //1.创建子线程
    randThread *rand=new randThread;//生成随机数
    buddleSort *buddle=new buddleSort;
    //2.启动生成随机数的子线程
    connect(this,&Widget::sendnum,rand,&randThread::recv);//向子线程发送数量
    connect(ui->start,&QPushButton::clicked,this,[=](){
         emit sendnum(10000);
         rand->start();
    });
    connect(rand,&randThread::sendVector,buddle,&buddleSort::recvArray);
    //主线程接收子线程发送过来的随机数组
    connect(rand,&randThread::sendVector,this,[=](QVector<int> array){
        ui->rand->clear();
        for(int i=0;i<array.size();i++){
            ui->rand->addItem(QString::number(array.at(i)));
        }
        buddle->start();
    });
    connect(buddle,&buddleSort::finish,this,[=](QVector<int> array){
        ui->buddle->clear();
        foreach(auto str,array){
            ui->buddle->addItem(QString::number(str));
        }
    });
    quickSort *quick=new quickSort;
    connect(rand,&randThread::sendVector,quick,&quickSort::recvArray);
    QThread *mythread=new QThread;
    quick->moveToThread(mythread);
    mythread->start();
    connect(rand,&randThread::starting,quick,&quickSort::working);
    connect(quick,&quickSort::sendResult,this,[=](QVector<int> array){
        for(int i=0;i<array.size();i++){
            ui->quick->addItem(QString::number(array.at(i)));
        }
    });
    //资源释放
    connect(this,&Widget::destroyed,this,[=](){
        rand->quit();
        rand->wait();
        delete rand;

        buddle->quit();
        buddle->wait();
        delete buddle;

        mythread->quit();
        mythread->wait();
        delete quick;
        delete mythread;
    });
}

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

下面是运行结果:

可以看到三个线程的地址不同,说明任务执行成功且是在不同的线程里执行的。

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值