目录
一.介绍
二.第一种多线程方式
1.创建一个线程子类,继承QT中的QThread
2.重新父类的run( )方法
3.在线程中创建子线程对象
4.run( )方法
5.启动子线程
三.第二种多线程方式
1.创建一个新类(这个类是QObject的派生)
2.在这个类中添加一个公共成员函数
3.主线程中创建一个QThread对象(子线程对象)
4.主线程中创建工作的类对象
5.将工作的类移动到子线程中,启动子线程
6.让工作的对象开始工作
7.工作函数
四.效果演示
五.代码演示
第一种线程方法
第二种线程方法
六.总结
一.介绍
QT中的线程用于实现多任务并发执行,提高程序的执行效率和响应速度。
在QT中,线程是进行运算调度的最小单位,它们包含在进程之中并作为进程中的实际运作单位。使用线程的主要目的是让程序能够同时执行多个任务。以下是QT线程的主要作用和使用方式:
- 提高性能和响应速度:通过将耗时的操作放在单独的线程中执行,可以避免UI冻结,提高应用程序的响应速度。
- 实现多任务处理:一个进程中可以并发运行多个线程,每条线程并行执行不同的任务,有效地利用了计算机多核处理器的能力。
- 简化复杂操作:对于需要长时间运行或复杂的计算,使用线程可以使主线程保持不被阻塞,从而不影响用户界面的交互性。
- 跨平台支持:QT提供的线程类如QThread、QThreadStorage等,都是跨平台的,可以在不同操作系统中使用。
- 提供线程安全的通信机制:QT支持线程安全的事件投递、跨线程的信号-槽连接,使得不同线程间的通信变得安全高效。
QT通过提供一系列与线程相关的类和方法,使得在应用程序中创建和管理线程变得相对简单。这包括继承QThread类并重写其run()方法来定义线程的行为,以及使用Qt的信号和槽机制来处理线程间通信。
二.第一种多线程方式
1.创建一个线程子类,继承QT中的QThread
2.重新父类的run( )方法
3.在线程中创建子线程对象
4.run( )方法
5.启动子线程
三.第二种多线程方式
1.创建一个新类(这个类是QObject的派生)
2.在这个类中添加一个公共成员函数
.
3.主线程中创建一个QThread对象(子线程对象)
4.主线程中创建工作的类对象
5.将工作的类移动到子线程中,启动子线程
6.让工作的对象开始工作
7.工作函数
四.效果演示
五.代码演示
第一种线程方法
mythread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QObject>
#include <QDebug>
#include <QVector>
#include <QThread>
class MyThread : public QThread
{
Q_OBJECT
public:
explicit MyThread(QObject *parent = nullptr);
protected:
void run();
signals:
//自定义信号,传递数据
void curNumber(int num);
public slots:
private:
};
#endif // MYTHREAD_H
mythread.cpp
#include "mythread.h"
#include <QDebug>
MyThread::MyThread(QObject *parent) : QThread(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.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "mythread.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
qDebug()<<"主线程对象地址"<<QThread::currentThread();
//创建子线程
MyThread* subThread = new MyThread;
connect(subThread,&MyThread::curNumber,this,[=](int num){
ui->label->setNum(num);
});
connect(ui->startBtn, &QPushButton::clicked, this, [=]()
{
// 启动子线程
subThread->start();
});
}
MainWindow::~MainWindow()
{
delete ui;
}
第二种线程方法
mythread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QObject>
#include <QDebug>
class MyThread : public QObject
{
Q_OBJECT
public:
explicit MyThread(QObject *parent = nullptr);
void working();
signals:
//自定义信号,传递数据
void curNumber(int num);
public slots:
private:
};
#endif // MYTHREAD_H
mythread.cpp
#include "mythread.h"
#include <QDebug>
#include <QThread>
MyThread::MyThread(QObject *parent) : QObject(parent)
{
}
void MyThread::working()
{
qDebug() << "当前线程对象的地址: " << QThread::currentThread();
int num = 0;
while(1)
{
emit curNumber(num++);
if(num == 10000000)
{
break;
}
QThread::usleep(1);
}
qDebug() << "run() 执行完毕, 子线程退出...";
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "mythread.h"
#include <QDebug>
#include <QThread>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
qDebug()<<"主线程对象地址"<<QThread::currentThread();
//创建线程对象
QThread* sub = new QThread;
//创建工作类对象
//千万不要指定给创建的对象指定父对象
//如果指定了: QObject::moveToThread: Cannot move objects with a parent
MyThread* work = new MyThread;
// 将工作的类对象移动到创建的子线程对象中
work->moveToThread(sub);
//启动线程
sub->start();
// 让工作的对象开始工作, 点击开始按钮, 开始工作
connect(ui->startBtn, &QPushButton::clicked, work, &MyThread::working);
//显示数据
connect(work,&MyThread::curNumber,this,[=](int num){
ui->label->setNum(num);
});
}
MainWindow::~MainWindow()
{
delete ui;
}
六.总结
继承QThread的方法只有重写run函数里的内容在子线程里运行,其他部分比如定时器的槽函数在主线程里运行。
MoveToThread的方法,所有的槽函数都在子线程里运行。