Qt多线程使用

一、QThread类介绍

        Qt中实现多线程需要使用线程类QThread。

        主要接口:start() 开始线程

        虚函数:virtual void run() 线程的运行run函数。虚函数子类重新实现

        信号函数:finished() 线程运行结束会发出此信号

二、多线程的2种实现方式

        1、重写run函数

        (1)定义线程类,继承自QThread

          (2)在线程类内实现run()函数

        (3)在需要创建子线程位置,创建定义的线程类对象 t

          (4)调用start函数, t->start(),现成启动,run函数种代码开始运行

#include <QThread> 

// WorkerThread 类继承自QThread
class WorkerThread : public QThread
  {
      Q_OBJECT
        
        // 重写虚函数run函数,函数内代码在子线程中运行
      void run() override {
          QString result;
          /* ... here is the expensive or blocking operation ... */
          emit resultReady(result);    // 现成结束发射信号
      }

  signals:
      void resultReady(const QString &s);
  };

  void MyObject::startWorkInAThread()
  {
        // 创建自定义线程类对象
      WorkerThread *workerThread = new WorkerThread(this);
    // 绑定线程结束信号
      connect(workerThread, &WorkerThread::resultReady, this, &MyObject::handleResults);
      connect(workerThread, &WorkerThread::finished, workerThread, &QObject::deleteLater);

    // 启动线程
      workerThread->start();
  }
2、借助moveToThread函数
// 定义线程工作类,槽函数doWork中代码在子线程中运行
class Worker : public QObject
  {
      Q_OBJECT

  public slots:
      void doWork(const QString &parameter) {
          QString result;
          /* ... here is the expensive or blocking operation ... */
          emit resultReady(result);
      }

  signals:
      void resultReady(const QString &result);
  };

    // 启动子线程
  class Controller : public QObject
  {
      Q_OBJECT
    // 由于Worker 类没有继承QThread, 定义线程对象QThread 
      QThread workerThread;
  public:
      Controller() {
        // 创建对象
          Worker *worker = new Worker;
        // 把对象移动到线程中
          worker->moveToThread(&workerThread);

        // 绑定线程结束信号
          connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);

        // 信号槽关联。当信号operate被发射时,槽函数doWork的执行是在子线程中执行的。
          connect(this, &Controller::operate, worker, &Worker::doWork);
        // 绑定线程信号
          connect(worker, &Worker::resultReady, this, &Controller::handleResults);

        // 线程启动,启动之后信号operate发射,doWork才会在子线程中运行
          workerThread.start();
      }
      ~Controller() {
          workerThread.quit();
          workerThread.wait();
      }
  public slots:
      void handleResults(const QString &);
  signals:
      void operate(const QString &);
  };

        (1)定义子线程处理类work,继承自QObject

        (2)定义几个槽函数,槽函数实现线程需要处理的代码

        (3)在需要运行子线程位置,创建work对象,创建QThread对象 t

        (4)work->moveToThread(t);

          (5)使用信号函数,关联work的槽函数

        (6)t.start()开启线程

        (7)发射信号,work槽函数开始在子线程中运行

三、两种实现方式对比

        第一种方式

                每次增加以一个线程,都会增加一个类

        第二种方式

                关联多个槽函数时,涉及到槽函数调用先后排队问题

四、多线程使用注意事项

        1. 业务对象, 构造的时候不能指定父对象

        2. 子线程中不能处理ui窗口(ui相关的类)

        3. 子线程中只能处理一些数据相关的操作, 不能涉及窗口

        如果需要把数据显示到UI,绑定信号与槽函数,发射信号,在主线程更新UI数据。

五、使用QThread实现多线程总结

优点:

  1. 控制灵活: QThread 提供了丰富的接口,允许开发者对线程的生命周期和行为进行细粒度的控制。
  2. 资源共享: 可以方便地在主线程和工作线程之间共享数据,通过 moveToThread 方法将对象移至特定线程。
  3. 线程间通信: 可以使用 QObject 的信号和槽机制实现线程安全地通信。
  4. 适用于复杂应用: 对于需要精细控制线程的应用,QThread 是一个很好的选择。

缺点:

  1. 编程复杂性: 需要手动管理线程的创建、执行和销毁,增加了编程的复杂性。
  2. 资源消耗: 每个线程都需要独立的栈空间,如果创建大量线程,可能会消耗较多的系统资源。
  3. 线程同步: 需要手动处理线程间的同步问题,如使用互斥锁(QMutex)等,增加了出错的可能性。

六、使用QtConcurrent 实现多线程

        


  
  MyClass myObject;
  
  // 定义监视线程对象,线程函数参数为int
  QFutureWatcher<int> watcher;

  // 关联线程完成信号,线程执行完后发射信号finished,handleFinished槽函数执行
  connect(&watcher, SIGNAL(finished()), &myObject, SLOT(handleFinished()));

  // Start the computation.
  // 线程执行函数  ,runWork函数为MyClass 类中的public普通函数
  QFuture<int> future = QtConcurrent::run(myObject, &MyClass::runWork,10);
  // 启动线程
  watcher.setFuture(future);

优点:

  1. 简化编程: QtConcurrent 提供了简化的 API,如 run 函数,可以很容易地在多线程中运行函数或算法。
  2. 易于使用: 对于简单的并行计算任务,QtConcurrent 提供了一种更简洁和易于使用的方法。
  3. 自动管理线程: QtConcurrent 会自动管理线程的创建和销毁,减少了开发者的负担。
  4. 支持并行模式: QtConcurrent 支持不同的并行模式,如线程池模式,可以有效地利用系统资源。

缺点:

  1. 控制有限: 相比 QThreadQtConcurrent 提供的控制接口较为有限,不适合需要精细控制线程的场景。
  2. 不适合I/O密集型任务: QtConcurrent 主要适用于计算密集型任务,对于 I/O 密集型任务,可能不会带来太大的性能提升。
  3. 资源共享困难: 与 QThread 相比,QtConcurrent 在资源共享方面不如 QThread 方便

七、总结

        选择使用 QThread 还是 QtConcurrent 取决于具体的应用场景和需求。如果需要对线程进行细粒度的控制,或者应用较为复杂,QThread 是更好的选择。如果任务相对简单,或者希望简化并行编程的复杂性,QtConcurrent 是一个不错的选择。在实际开发中,也可以根据需要将两者结合使用。

        关于面试的话会问到如何使用QThread类创建线程相关知识。

  • 13
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值