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;
}
下面是运行结果:
可以看到三个线程的地址不同,说明任务执行成功且是在不同的线程里执行的。