多线程的创建

重写QThread类的run方法
  1. 通过重写QThread类的run方法实现多线程的创建,实现的run方法将作为线程执行体。
  2. 示例如下:将复杂的计算任务交给子线程处理,主线程负责获取计算结果并展示在UI界面上
    1. 自定义类继承自QThread类,并重写run方法
    #ifndef WORKER_H
    #define WORKER_H
    
    #include <QThread>
    
    class Worker : public QThread
    {
        Q_OBJECT
    public:
        Worker();
    
        // 获取计算结果
        int getResult() const { return result; }
    
    protected:
        void run() override;
    
    private:
        int result;
    };
    
    #endif // WORKER_H
    
    #include "worker.h"
    
    Worker::Worker() : result(0)
    {
    }
    
    /**
     * @brief Worker::run 子线程执行的计算任务逻辑
     */
    void Worker::run()
    {
        result = 0;
        for(int i = 1; i <= 100; ++i) {
            result += i;
        }
    }
    
    
    1. 主线程可以在页面某个元素的回调函数中开启子线程执行计算耗时逻辑,然后获取其计算的值渲染在页面上
    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    
    #include "worker.h"
    
    QT_BEGIN_NAMESPACE
    namespace Ui {
    class MainWindow;
    }
    QT_END_NAMESPACE
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
    private slots:
        void on_startButton_clicked();
    
    private:
        Ui::MainWindow *ui;
    
        Worker *worker;
    };
    #endif // MAINWINDOW_H
    
    #include "mainwindow.h"
    #include "./ui_mainwindow.h"
    #include <QMessageBox>
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
        , worker(new Worker)
    {
        ui->setupUi(this);
    }
    
    MainWindow::~MainWindow()
    {
        if (worker->isRunning()) {
            worker->terminate();
            worker->wait();
        }
        delete worker;
        delete ui;
    }
    
    void MainWindow::on_startButton_clicked()
    {
        worker->start();
        worker->wait(); // 等待线程完成
    
        int sum = worker->getResult();
        QMessageBox::information(this, "结果", QString("1到100的和是:%1").arg(sum));
    }
    
    
使用信号与槽机制

使用信号与槽机制:主要使用moveToThread方法

  1. 创建QThread类对象作为新线程
  2. 创建执行体,在执行体的槽函数中实现线程的执行逻辑,以信号的方式传递数据
  3. 创建执行体对象,并使用QObject::moveToThread()将其移动到新线程
  4. 在主线程中通过连接信号与槽的方式,间接调用执行体对象的槽函数,从而启动执行新线程。
  5. 示例如下:
#include <QThread>
#include <QObject>
#include <QDebug>

class Worker : public QObject
{
    Q_OBJECT

public slots:
    void doWork() {
        for (int i = 0; i < 5; ++i) {
            qDebug() << "Worker running:" << i;
            QThread::sleep(1);
        }
    }
};

int main(int argc, char *argv[])
{
    QThread workerThread;
    Worker worker;
    worker.moveToThread(&workerThread);

    QObject::connect(&workerThread, &QThread::started, &worker, &Worker::doWork);
    QObject::connect(&workerThread, &QThread::finished, &worker, &QObject::deleteLater);

    workerThread.start();
    workerThread.wait();
    return 0;
}
使用线程池

预先创建一批线程,当需要新线程执行任务时,可以将任务提交到线程池中的某一个线程中执行

多线程同步

  1. 互斥锁:QMutex及QMutexLocker
  2. 信号量:QSemaphore
  3. 条件变量结合互斥锁:QWaitCondition+QMutexLocker