qt中的多线程

阅读数:72 评论数:0

跳转到新版页面

分类

C/C++

正文

一、基本概念

在 Qt 中,QThread 类用于表示一个线程。你可以通过继承 QThread 或者将对象移动到线程来实现多线程编程。推荐的方法是将对象移动到线程,因为它更符合 Qt 的信号槽机制。

二、创建和启动线程

1、继承QThread

这种方法通过继承 QThread 并重写 run 方法来实现线程任务。

#include <QThread>
#include <QDebug>

class MyThread : public QThread {
    Q_OBJECT

protected:
    void run() override {
        for (int i = 0; i < 5; ++i) {
            qDebug() << "Thread running" << i;
            QThread::sleep(1);
        }
    }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    MyThread thread;
    thread.start();
    thread.wait(); // 等待线程结束

    return app.exec();
}

2、将对象移动到线程

这种方法更推荐,因为它更符合 Qt 的信号槽机制,并且更容易管理对象的生命周期。

#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[]) {
    QApplication app(argc, 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 app.exec();
}

三、线程间通信

Qt 的信号槽机制可以跨线程工作。你可以使用信号槽在线程之间传递数据。

#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;
            emit progress(i);
            QThread::sleep(1);
        }
        emit finished();
    }

signals:
    void progress(int value);
    void finished();
};

class Controller : public QObject {
    Q_OBJECT

public slots:
    void onProgress(int value) {
        qDebug() << "Progress:" << value;
    }

    void onFinished() {
        qDebug() << "Task finished!";
    }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    QThread workerThread;
    Worker worker;
    Controller controller;

    worker.moveToThread(&workerThread);
    QObject::connect(&workerThread, &QThread::started, &worker, &Worker::doWork);
    QObject::connect(&worker, &Worker::progress, &controller, &Controller::onProgress);
    QObject::connect(&worker, &Worker::finished, &controller, &Controller::onFinished);
    QObject::connect(&worker, &Worker::finished, &workerThread, &QThread::quit);
    QObject::connect(&workerThread, &QThread::finished, &worker, &QObject::deleteLater);

    workerThread.start();

    return app.exec();
}

四、线程安全

在多线程编程中,确保线程安全非常重要。Qt 提供了 QMutexQReadWriteLockQSemaphore 等类来实现线程同步。

1、使用QMutex保护共享数据

#include <QThread>
#include <QMutex>
#include <QDebug>

class Counter {
public:
    void increment() {
        QMutexLocker locker(&mutex);
        ++value;
        qDebug() << "Counter value:" << value;
    }

private:
    int value = 0;
    QMutex mutex;
};

class Worker : public QThread {
    Q_OBJECT

public:
    Worker(Counter *counter) : counter(counter) {}

protected:
    void run() override {
        for (int i = 0; i < 5; ++i) {
            counter->increment();
            QThread::sleep(1);
        }
    }

private:
    Counter *counter;
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    Counter counter;
    Worker worker1(&counter);
    Worker worker2(&counter);

    worker1.start();
    worker2.start();

    worker1.wait();
    worker2.wait();

    return app.exec();
}

五、线程池

Qt 提供了 QThreadPoolQRunnable 来管理和执行多个线程任务。线程池可以重复使用线程,从而减少线程创建和销毁的开销。

#include <QThreadPool>
#include <QRunnable>
#include <QDebug>

class Task : public QRunnable {
public:
    void run() override {
        for (int i = 0; i < 5; ++i) {
            qDebug() << "Task running" << i;
            QThread::sleep(1);
        }
    }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    QThreadPool pool;
    Task *task1 = new Task();
    Task *task2 = new Task();

    pool.start(task1);
    pool.start(task2);

    pool.waitForDone();

    return app.exec();
}



相关推荐