7.1 多线程 QThread 与 Qt Concurrent

7.1 多线程 QThread 与 Qt Concurrent

Qt 提供了多种方法实现多线程编程,包括低层次的 QThread 类和高层次的 Qt Concurrent 模块。多线程编程是现代应用程序中提升性能和响应能力的重要手段,特别是对于需要大量计算或 I/O 操作的场景。


一、多线程编程的基础概念

在 Qt 中,多线程的基本原理是将耗时操作从主线程(GUI 线程)分离到其他线程,以避免阻塞用户界面。

线程的分类
  1. 主线程:默认的 GUI 线程,负责用户界面的绘制和交互。
  2. 工作线程:用于执行后台任务,如文件读写、网络请求、数据处理等。

二、QThread 类

QThread 是 Qt 提供的底层线程类,允许开发者直接管理线程的生命周期和运行逻辑。

使用步骤
  1. 创建一个继承自 QThread 的类。
  2. 在子类中重写 run() 方法,定义线程运行逻辑。
  3. 使用 start() 启动线程。
示例:创建一个简单的工作线程
#include <QThread>
#include <QDebug>

class WorkerThread : public QThread {
    Q_OBJECT
protected:
    void run() override {
        for (int i = 0; i < 5; ++i) {
            qDebug() << "Worker thread running:" << i;
            QThread::sleep(1); // 模拟耗时操作
        }
    }
};

int main() {
    WorkerThread thread;
    thread.start();
    thread.wait(); // 等待线程完成
    return 0;
}
注意事项
  • 不要直接在 run() 方法中操作 GUI。
  • 使用信号和槽在线程间传递数据。

三、Qt Concurrent 模块

Qt Concurrent 提供了一种更高层次的接口,简化了多线程编程,适合并行执行大量任务。

常用功能
  1. QtConcurrent::run:将函数或成员函数作为任务运行。
  2. QtConcurrent::map:对容器中的每个元素并行执行操作。
  3. QtConcurrent::filter:对容器中的元素进行并行过滤。
示例 1:并行执行任务
#include <QtConcurrent>
#include <QDebug>

void longTask(int value) {
    qDebug() << "Processing value:" << value;
    QThread::sleep(1); // 模拟耗时操作
}

int main() {
    QList<int> values = {1, 2, 3, 4, 5};
    QtConcurrent::map(values, longTask);
    return 0;
}
示例 2:任务的返回值
#include <QtConcurrent>
#include <QFuture>
#include <QDebug>

int calculateSquare(int value) {
    return value * value;
}

int main() {
    QFuture<int> future = QtConcurrent::run(calculateSquare, 10);
    future.waitForFinished();
    qDebug() << "Result:" << future.result();
    return 0;
}

四、线程间通信

线程间通信是多线程编程的核心,Qt 提供了以下几种机制:

  1. 信号与槽:线程安全的通信方式。
  2. 事件队列:通过 QCoreApplication::postEvent 向目标线程发送事件。
  3. 共享资源保护:使用互斥锁(QMutex)、读写锁(QReadWriteLock)等确保数据一致性。
  4. 消息队列:通过 QThread::msleep() 和信号量(QSemaphore)实现线程间等待与同步。
信号与槽示例:实现线程间的任务触发
#include <QThread>
#include <QDebug>

class Worker : public QObject {
    Q_OBJECT
public slots:
    void doWork() {
        qDebug() << "Work started in thread:" << QThread::currentThread();
    }
};

int main() {
    QThread thread;
    Worker worker;

    worker.moveToThread(&thread);
    QObject::connect(&thread, &QThread::started, &worker, &Worker::doWork);
    thread.start();
    thread.wait();

    return 0;
}
事件队列示例:基于事件的通信
#include <QCoreApplication>
#include <QThread>
#include <QDebug>

class CustomEvent : public QEvent {
public:
    static const QEvent::Type EventType = static_cast<QEvent::Type>(QEvent::User + 1);
    CustomEvent(const QString& message) : QEvent(EventType), msg(message) {}
    QString msg;
};

class EventReceiver : public QObject {
    Q_OBJECT
protected:
    bool event(QEvent* event) override {
        if (event->type() == CustomEvent::EventType) {
            CustomEvent* customEvent = static_cast<CustomEvent*>(event);
            qDebug() << "Received event with message:" << customEvent->msg;
            return true;
        }
        return QObject::event(event);
    }
};

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

    EventReceiver receiver;
    QCoreApplication::postEvent(&receiver, new CustomEvent("Hello from another thread!"));

    return app.exec();
}
共享资源保护示例:避免数据竞争
#include <QThread>
#include <QMutex>
#include <QDebug>

class SharedResource {
    QMutex mutex;
    int counter = 0;

public:
    void increment() {
        QMutexLocker locker(&mutex);
        ++counter;
        qDebug() << "Counter incremented to:" << counter;
    }
};

class Worker : public QThread {
    SharedResource* resource;

public:
    Worker(SharedResource* res) : resource(res) {}

protected:
    void run() override {
        for (int i = 0; i < 10; ++i) {
            resource->increment();
            msleep(50);
        }
    }
};

int main() {
    SharedResource resource;

    Worker worker1(&resource);
    Worker worker2(&resource);

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

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

    return 0;
}
信号量示例:线程同步
#include <QThread>
#include <QSemaphore>
#include <QDebug>

QSemaphore semaphore;

class Producer : public QThread {
protected:
    void run() override {
        for (int i = 0; i < 5; ++i) {
            semaphore.release();
            qDebug() << "Produced item" << i;
            QThread::sleep(1);
        }
    }
};

class Consumer : public QThread {
protected:
    void run() override {
        for (int i = 0; i < 5; ++i) {
            semaphore.acquire();
            qDebug() << "Consumed item" << i;
        }
    }
};

int main() {
    Producer producer;
    Consumer consumer;

    producer.start();
    consumer.start();

    producer.wait();
    consumer.wait();

    return 0;
}

五、性能优化建议

  1. 任务粒度:将大任务分解为多个小任务,避免线程空闲或过载。
  2. 线程池:使用 QThreadPool 管理线程,避免频繁创建和销毁线程。
  3. 避免竞态条件:使用锁或原子操作保护共享数据。
  4. 减少锁争用:尽量缩小锁的作用范围。

Qt 的多线程和并行编程工具为开发者提供了灵活高效的解决方案。根据项目需求选择合适的工具,可以大幅提升程序性能和用户体验

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值