QT中多线程实现的三种方式
在Qt中经常会遇到耗时操作,需要并发执行,建立线程的主要目的就是为了用线程来处理那些耗时的后台操作
基类Widget
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
namespace Ui {
class Widget;
}
struct WidgetPrivate;
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr);
~Widget();
private:
Ui::Widget *ui;
struct WidgetPrivate *p;
};
#endif // WIDGET_H
第一种方式:继承QThread 重写run方法
需要定义一个新类,继承QThread,并且重写QThread类的run()方法,在run()方法中实现线程所需要处理的逻辑代码
generate.h
#ifndef GENERATE_H
#define GENERATE_H
#include <QThread>
#include <QObject>
class Generate : public QThread
{
Q_OBJECT
public:
explicit Generate(QObject *parent = nullptr);
signals:
void GenerateFinished(std::vector<int> NumList);
protected:
void run();
};
#endif // GENERATE_H
generate.cpp
#include "generate.h"
#include <QDebug>
#include <vector>
#include<QThread>
Generate::Generate(QObject *parent):QThread(parent)
{
}
void Generate::run()
{
// qDebug()<<"生成随机数:"<<QThread::currentThread();
std::vector<int> NumList;
for(int i=0; i<100000; i++)
{
NumList.push_back(qrand()%100000);
}
emit GenerateFinished(NumList);
}
Widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
#include <QThreadPool>
#include "generate.h"
struct WidgetPrivate
{
};
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget),p(new WidgetPrivate)
{
ui->setupUi(this);
//第一种方式 继承QThread 重写run方法
Generate *g = new Generate;
connect(ui->pushButton,&QPushButton::clicked,[=](){
g->start();
});
//插入ListWidget
connect(g,&Generate::GenerateFinished,[=](std::vector<int> NumList){
for(int i=0; i<NumList.size(); i++)
ui->listWidget->addItem(QString::number(NumList[i]));
});
}
Widget::~Widget()
{
delete ui;
delete p;
}
注意,不要直接调用 UI 相关的操作
第二种方式:继承QObject,movetothread
该方式是通过继承 QObject并使用 movetothread 函数将对象移到指定线程中。这种方式允许你将任务逻辑放在一个单独的类中,然后将该类对象移动到新线程中执行。
movetothread.h
#ifndef MOVETOTHREAD_H
#define MOVETOTHREAD_H
#include <QObject>
class MoveToThread : public QObject
{
Q_OBJECT
public:
explicit MoveToThread(QObject *parent = nullptr);
void Generate();
signals:
void GenerateFinished(std::vector<int>NumList);
public slots:
};
#endif // MOVETOTHREAD_H
movetothread.cpp
#include "movetothread.h"
#include<QThread>
#include<QDebug>
MoveToThread::MoveToThread(QObject *parent) : QObject(parent)
{
}
void MoveToThread::Generate()
{
qDebug()<<"生成随机数:"<<QThread::currentThread();
std::vector<int>NumList;
for(int i=0;i<100000;i++)
{
NumList.push_back(qrand()%100000);
}
emit GenerateFinished(NumList);
}
Widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
#include "movetothread.h"
struct WidgetPrivate
{
};
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget),p(new WidgetPrivate)
{
ui->setupUi(this);
//第二种 继承QObject,movetothread
QThread *t = new QThread;
MoveToThread *m = new MoveToThread;
//把整个类的对象都放到线程中
m->moveToThread(t);
//选择执行Generate
connect(t,&QThread::started,[=]()
{
m->Generate();
});
//启动线程
connect(ui->pushButton,&QPushButton::clicked,[=]()
{
t->start();
});
connect(m,&MoveToThread::GenerateFinished,[=](std::vector<int> NumList){
for(int i=0; i<NumList.size(); i++)
ui->listWidget->addItem(QString::number(NumList[i]));
});
}
Widget::~Widget()
{
delete ui;
delete p;
}
第三种方式:使用QT的 QThreadPool 类, 继承QRunnable,重写run函数
QThreadPool可以管理多个线程,并且在线程中运行QRunnable对象的任务,更加灵活
poolgenerate.h
#ifndef POOLGENERATE_H
#define POOLGENERATE_H
#include <QObject>
#include <QWidget>
#include <QRunnable>
#include <vector>
class PoolGenerate : public QObject,public QRunnable
{
Q_OBJECT
public:
explicit PoolGenerate(QObject *parent = nullptr);
void run() override;
signals:
void GenerateFinished(std::vector<int>NumList);
public slots:
};
#endif // POOLGENERATE_H
poolgenerate.cpp
#include "poolgenerate.h"
#include<QDebug>
#include<QThread>
PoolGenerate::PoolGenerate(QObject *parent) : QObject(parent)
{
}
void PoolGenerate::run()
{
qDebug()<<"生成随机数:"<<QThread::currentThread();
std::vector<int>NumList;
for(int i=0;i<100000;i++)
{
NumList.push_back(qrand()%100000);
}
emit GenerateFinished(NumList);
}
Widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
#include <QThreadPool>
#include "poolgenerate.h"
struct WidgetPrivate
{
};
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget),p(new WidgetPrivate)
{
ui->setupUi(this);
//第三种 使用QT的 QThreadPool 类, 继承QRunnable,重写run函数
PoolGenerate *pool = new PoolGenerate;
connect(ui->pushButton,&QPushButton::clicked,[=]()
{
QThreadPool::globalInstance()->start(pool);
});
connect(pool,&PoolGenerate::GenerateFinished,[=](std::vector<int>NumList)
{
for(int i=0;i<NumList.size();i++)
{
ui->listWidget->addItem(QString::number(NumList[i]));
}
});
}
Widget::~Widget()
{
delete ui;
delete p;
}