【QT 多线程示例】两种多线程实现方式

文章目录

多线程实现

在Qt中,实现多线程编程有两种常见的方式,它们分别是通过继承QThread类和使用QObject::moveToThread()方法。

方式一:继承QThread类

通过继承QThread类并重写其run()方法,可以在新线程中执行特定的任务。

具体步骤

  1. 创建自定义线程类 :继承QThread类,并重写run()方法。在run()方法中编写需要在新线程中执行的代码。

  2. 创建线程对象:在主线程中创建自定义线程类的实例。

  3. 启动线程 :调用线程对象的start()方法启动线程。此时,Qt会创建一个新的线程,并在该线程中调用run()方法。

  4. 线程间通信:可以通过信号和槽机制在主线程和子线程之间进行通信。自定义线程类可以发射信号,主线程可以连接这些信号到相应的槽函数,以处理线程返回的数据或状态。

示例代码
https://github.com/BinaryAI-1024/QtStudy/tree/master/thread/createThread1

cpp 复制代码
// mythread.h
#include <QThread>
#include <QDebug>


class Mythread: public QThread{
    Q_OBJECT
public:
    explicit Mythread(QObject *parent = nullptr);
    void run();

};
cpp 复制代码
// mythread.cpp
#include "Mythread.h"

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

}


void Mythread::run(){

    // 在新线程中执行的代码
    for (int i = 0; i < 5; ++i) {
        qDebug() << "Worker thread is running... (" << i << ")";
        QThread::sleep(1); // 模拟耗时操作
    }
}
cpp 复制代码
//main.cpp
#include <QCoreApplication>
#include "Mythread.h"
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    Mythread thread1;
    thread1.start();


    for (int i = 0; i < 5; ++i) {
        qDebug() << "Main thread is running... (" << i << ")";
        QThread::sleep(1); // 模拟耗时操作
    }

    thread1.wait(); // 等待直到thread1线程结束
    return a.exec();
}

运行结果:

复制代码
Main thread is running... ( 0 )
Worker thread is running... ( 0 )
Worker thread is running... ( 1 )
Main thread is running... ( 1 )
Worker thread is running... ( 2 )
Main thread is running... ( 2 )
Worker thread is running... ( 3 )
Main thread is running... ( 3 )
Main thread is running... ( 4 )
Worker thread is running... ( 4 )

优缺点分析

  • 优点:实现简单,适合需要在新线程中执行单一任务的场景。

  • 缺点

    • 强制将业务逻辑与线程控制代码耦合在一起,不利于代码的复用和维护。
    • 需要手动管理线程的生命周期,增加了代码的复杂性。

方式二: 使用QObject::moveToThread()方法

通过将QObject(或其子类)的实例移动到新线程中,可以在该线程中执行该对象的方法。这种方法更加灵活,不需要继承QThread类。

具体步骤

  1. 创建工作对象 :定义一个继承自QObject的类,并在其中定义需要在新线程中执行的方法(槽函数)。

  2. 创建线程对象 :在主线程中创建一个QThread实例。

  3. 移动对象到线程 :调用工作对象的moveToThread()方法,将其移动到新创建的线程中。

  4. 启动线程并调用槽函数

    • 调用线程对象的start()方法启动线程。
    • 使用信号和槽机制,在主线程中发射信号,触发工作对象在新线程中执行的槽函数。
  5. 线程间通信:同样可以通过信号和槽机制在主线程和工作线程之间进行通信。工作线程可以发射信号,主线程连接这些信号到相应的槽函数,以处理线程返回的数据或状态。

示例代码
https://github.com/BinaryAI-1024/QtStudy/tree/master/thread/createThread2

cpp 复制代码
//myworker.h
#include <QObject>
class MyWorker : public QObject
{
public:
    explicit MyWorker(QObject *parent = nullptr);
    void working();

};
cpp 复制代码
//myworker.cpp
#include <QDebug>
#include <QThread>
#include "myworker.h"

MyWorker::MyWorker(QObject *parent) : QObject(parent)
{

}


void MyWorker:: working(){
    // 在新线程中执行的代码
    for (int i = 0; i < 5; ++i) {
        qDebug() << "Worker thread is running... (" << i << ")";
        QThread::sleep(1); // 模拟耗时操作
    }

}
cpp 复制代码
//main.cpp
#include <QCoreApplication>
#include <QThread>
#include <QDebug>
#include "myworker.h"


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QThread thread1;
    MyWorker worker;

    // 将 worker 对象移动到 thread1 线程中,以便 working 函数在 thread1 中执行
    worker.moveToThread(&thread1);

    // 连接 QThread 的 started 信号到 MyWorker 的 working 槽函数
    // 当 thread1 启动时,worker 的 working 函数会被调用
    QObject::connect(&thread1, &QThread::started, &worker, &MyWorker::working);
    // 启动 thread1 线程
    thread1.start();


    for (int i = 0; i < 5; ++i) {
        qDebug() << "Main thread is running... (" << i << ")";
        QThread::sleep(1); // 模拟耗时操作
    }

    thread1.wait();

    return a.exec();
}

运行结果:

复制代码
Main thread is running... ( 0 )
Worker thread is running... ( 0 )
Worker thread is running... ( 1 )
Main thread is running... ( 1 )
Worker thread is running... ( 2 )
Main thread is running... ( 2 )
Worker thread is running... ( 3 )
Main thread is running... ( 3 )
Main thread is running... ( 4 )
Worker thread is running... ( 4 )

优缺点分析

  • 优点

    • 将业务逻辑与线程控制代码分离,提高了代码的复用性和可维护性。
    • 可以方便地在多个线程之间移动对象,实现复杂的线程间交互。
  • 缺点:实现相对复杂一些,需要额外管理对象在新线程中的生命周期和信号槽连接。

相关推荐
我不是疯子是傻子6 分钟前
Qt 实时曲线卡顿优化:从QPainter到OpenGL的3级加速实战
开发语言·qt
zlinear数据采集卡7 分钟前
D223 ADC数据处理流水线:从原始采样值到工程单位的完整转换链
开发语言·arm开发·嵌入式硬件·fpga开发·开源·c#
nnerddboy1 小时前
Rust教程04:引用、借用与切片
开发语言·后端·rust
jerryinwuhan1 小时前
《Python数据预处理》第四章
开发语言·python
长江&后浪1 小时前
防火墙的描述
开发语言·网络·php
观无2 小时前
若依EasyExcel实现单元格合并
开发语言·前端·javascript
雨晨源码(同名B站)2 小时前
基于Python的网易云音乐评论数据情感化分析系统 音乐爬虫信息可视化 |SnowNLP评论情感分析
开发语言·hadoop·爬虫·python·信息可视化·毕业设计
我不是疯子是傻子2 小时前
串口通信数据帧粘包拆包再进化:基于 Qt 的滑动窗口与 CRC 校验实战
开发语言·qt
程序员老陆2 小时前
Qt中实现窗口真全屏(覆盖Windows任务栏)
开发语言·windows·qt
霸道流氓气质2 小时前
Java中信号量(Semaphore):从本地到分布式
java·开发语言·分布式