目录
qt为多线程提供了完美的支持,实现多线程一般是从从QTHread中继承定义自己的线程类,QT也提供了QMutexLocker,QwaitCondition等类实现线程同步,与Linux系统或C++中的线程库类似。这里简单介绍下多线程的创建。
常用API:

[virtual protected] void QThread::run();
run()是一个虚函数,如果想让创建的子线程执行某个任务,需要写一个子类让其继承QThread,并且在子类中重写父类的run()方法,函数体就是对应的任务处理流程,当前线程对象调用槽函数start()启动子线程,当子线程被启动,这个run()函数也就在线程内部被调用了。
信号与槽函数:
// 线程中执行的任务完成了, 发出该信号
[signal] void QThread::finished();
// 开始工作之前发出这个信号, 一般不使用
[signal] void QThread::started();[slot] void QThread::quit();
// 启动子线程
[slot] void QThread::start(Priority priority = InheritPriority);
// 线程退出, 可能是会马上终止线程, 一般情况下不使用这个函数
[slot] void QThread::terminate();
创建一个线程类的子类,让其继承QT中的线程类 QThread,重写父类的 run() 方法,启动子线程, 调用 start() 方法。
举例:
- #ifndef MYTHREAD_H
- #define MYTHREAD_H
-
- #include
- #include
-
- class MyThread : public QThread
- {
- Q_OBJECT
- public:
- explicit MyThread(QObject *parent = nullptr);
- protected:
- void run();
- signals:
- void curNumber(int num);
- };
-
- #endif // MYTHREAD_H
- #include "mythread.h"
- #include
- MyThread::MyThread(QObject *parent)
- {
- }
-
- void MyThread::run()
- {
- qDebug() << "当前线程对象的地址: " << QThread::currentThread();
-
- int num = 0;
- while(1)
- {
- emit curNumber(num++);//子线程每秒发出一次信号
- if(num == 10000000)
- {
- break;
- }
- QThread::usleep(1);
- }
- qDebug() << "run() 执行完毕, 子线程退出...";
-
- }
- MainWindow::MainWindow(QWidget *parent)
- : QMainWindow(parent)
- , ui(new Ui::MainWindow)
- {
- ui->setupUi(this);
-
- qDebug() << "主线程对象地址: " << QThread::currentThread();
- MyThread* m=new MyThread;
-
- connect(m, &MyThread::curNumber, this, [=](int num)//子线程每秒发出一次信号
- {
- ui->label->setNum(num);
- });
-
- connect(ui->pushButton, &QPushButton::clicked, this, [=]()
- {
- // 启动子线程
- m ->start();
- });
- }
-
- MainWindow::~MainWindow()
- {
- delete ui;
- }
例如:
- #ifndef WORK_H
- #define WORK_H
- #include
-
- class Work : public QObject
- {
- Q_OBJECT
- public:
- explicit Work(QObject *parent = nullptr);
- void Working();
- signals:
- void curNumber(int num);
-
- };
- #endif // WORK_H
- #include "work.h"
- #include
- #include
- Work::Work(QObject *parent)
- : QObject{parent}
- {
- }
-
- void Work::Working()
- {
- qDebug() << "当前线程对象的地址: " << QThread::currentThread();
-
- int num = 0;
- while(1)
- {
- emit curNumber(num++);//子线程每秒发出一次信号
- if(num == 10000000)
- {
- break;
- }
- QThread::usleep(1);
- }
- qDebug() << "run() 执行完毕, 子线程退出...";
- }
- MainWindow::MainWindow(QWidget *parent)
- : QMainWindow(parent)
- , ui(new Ui::MainWindow)
- {
- ui->setupUi(this);
-
- qDebug() << "主线程对象地址: " << QThread::currentThread();
-
- QThread* sub = new QThread;//创建线程对象
- Work* w=new Work; //创建工作对象,该对象包含业务处理方法,不要指定给创建的对象指定父对象
- w->moveToThread(sub); //将工作对象移动到子线程中
-
- sub->start();
- connect(ui->startBtn, &QPushButton::clicked, w,&Work::Working);
- // 显示数据
- connect(w, &Work::curNumber, this, [=](int num)
- {
- ui->label->setNum(num);
- });
- }
-
-
-
在一个子线程程中随机生成1000个数,将这些数据交给另一个子线程去排序,后面将排序的结果返回给主线程,主线程再将数据输出到窗口中。
这里采用方案1进行演示:
生成随机数线程:
- class Genera : public QThread //该类来生成随机数
- {
- Q_OBJECT
- public:
- explicit Genera(QObject *parent = nullptr);
- void getnum(int k);
- protected:
- void run();//重写run方法,生成随机数
- private:
- int num_; //获取主线程传来的数据,这里为生成随机数的个数
-
- signals:
- void sendnum(QVector<int> v);//当随机数生成完后,发射该信号,将数据传给主线程和排序线程
- };
-
-
- Genera::Genera(QObject *parent)
- : QThread{parent}
- {
- }
- void Genera::getnum(int k)
- {
- num_=k;
- }
- void Genera::run()
- {
- qDebug()<<"当前线程是"<<" "<
currentThread(); - QVector<int> v;
- QElapsedTimer q;
- q.start();
- for(int i=0;i
- {
- v.push_back(qrand()%10000);
- }
- int m=q.elapsed();
- qDebug()<<"生成随机的时间是"<<" "<
- emit sendnum(v);
-
- }
排序线程:
- class BubbleSort : public QThread //该类来生成随机数
- {
- Q_OBJECT
- public:
- explicit BubbleSort(QObject *parent = nullptr);
- void getnum(QVector<int>);//获取生成随机数线程传来的数据
- protected:
- void run();//进行排序
- private:
- QVector<int> v;
-
- signals:
- void Finish(QVector<int> v);//排序完成后发射该信号,将排序结果给主线程
- };
-
- BubbleSort::BubbleSort(QObject *parent)
- : QThread{parent}
- {
- }
- void BubbleSort::getnum(QVector<int> list)
- {
- v=list;
- }
- void BubbleSort::run()
- {
- qDebug()<<"当前线程是"<<" "<
currentThread(); - QElapsedTimer q;
- q.start();
- for(int i=0;i
size();i++) - {
- for(int j=0;j
size()-i-1;j++) - {
- if(v[j]>v[j+1])
- {
- int tmp=v[j+1];
- v[j+1]=v[j];
- v[j]=tmp;
- }
- }
- }
- int m=q.elapsed();
- qDebug()<<"排序的时间是"<<" "<
- emit Finish(v);
- }
主线程:
- class MainWindow : public QMainWindow
- {
- Q_OBJECT
-
- public:
- MainWindow(QWidget *parent = nullptr);
- ~MainWindow();
- signals:
- void starting(int num);//生成随机数的个数
-
- private:
- Ui::MainWindow *ui;
- };
- #endif // MAINWINDOW_H
-
-
- MainWindow::MainWindow(QWidget *parent)
- : QMainWindow(parent)
- , ui(new Ui::MainWindow)
- {
- ui->setupUi(this);
-
- //创建子线程
- Genera * g=new Genera;//生成随机数
- BubbleSort* b=new BubbleSort;//排序
- connect(this,&MainWindow::starting,g,&Genera::getnum);
-
- //启动子线程
- connect(ui->pushButton,&QPushButton::clicked,this,[=](){
- emit starting(1000);//发射该信号,将生成随机数的个数传给子线程
- g->start();
- });
-
-
- connect(g,&Genera::sendnum,b,&BubbleSort::getnum);//排序线程接受生成随机数线程传来的数据
-
- //接受子线程传来的排序数
- connect(g,&Genera::sendnum,this,[=](QVector<int> v){
- //说明随机生成数已生成好
- b->start();
- for(int i=0;i
size();i++) - {
- ui->listWidget->addItem(QString::number(v.at(i)));
- }
- });
-
- connect(b,&BubbleSort::Finish,this,[=](QVector<int> v){
-
- for(int i=0;i
size();i++) - {
- ui->listWidget_2->addItem(QString::number(v.at(i)));
- }
- });
- }
-
- MainWindow::~MainWindow()
- {
- delete ui;
- }
结果:

线程资源释放
1.创建线程时,给它指明父对象,让其添加到对象树列表中。
2.手动释放,调用quit,wait,delete:例如,在上面的代码中,new出来的时局部变量:
- connect(this,&MainWindow::destroyed,this,[=](){
- g->quit();
- g->wait();
- g->deleteLater();//类似与c++中delete
- });
-
相关阅读:
脚手架搭建项目package.json配置中依赖的版本问题
PyTorch混合精度原理及如何开启该方法
离散数学复习:特殊关系
实战演练 | 使用纯 SQL 将表复制到新表
Kubernetes 创建pod的yaml文件-简单版-nginx
网络编程——socket定义和地址格式
大二学生JavaScript实训大作业——动漫秦时明月7页 期末网页制作 HTML+CSS+JavaScript 网页设计实例 企业网站制作
【计算机组成原理】第一章单元测试
BIGEMAP APP行车(走路)轨迹记录
windows系统如何查看Linux文件系统中的图片缩略图
-
原文地址:https://blog.csdn.net/m0_64397669/article/details/133094645