前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >Qt5实战第七篇:Qt5多线程编程

Qt5实战第七篇:Qt5多线程编程

原创
作者头像
china马斯克
发布2024-12-31 08:01:44
发布2024-12-31 08:01:44
2030
举报

多线程编程是现代应用开发中不可或缺的一部分,尤其在处理复杂任务或需要提高程序响应速度时,多线程显得尤为重要。Qt5提供了一套强大的多线程支持,通过QThread类及其相关类,开发者可以方便地实现多线程功能。

一、线程基础

1.GUI线程与工作线程

  • 每个Qt程序启动后,拥有的第一个线程称为主线程,也叫GUI线程。Qt中的所有组件类和几个相关类只能工作在GUI线程中,不能工作在次线程(工作线程)中。工作线程主要负责处理GUI线程卸下的工作。
  • 每个线程都有自己的栈,因此每个线程都有自己的调用历史和本地变量。线程共享相同的地址空间。

2.Qt对线程的支持

  • Qt通过三种形式提供了对线程的支持:平台无关的线程类、线程安全的事件投递、跨线程的信号-槽连接。
  • 主要的Qt线程类包括:
    • QThread:提供了跨平台的多线程解决方案。
    • QThreadStorage:提供逐线程数据存储。
    • QMutex:提供相互排斥的锁,或互斥量。
    • QMutexLocker:一个辅助类,自动对QMutex加锁与解锁。
    • QReadWriterLock:提供一个可以同时读操作的锁。
    • QReadLockerQWriteLocker:自动对QReadWriteLock加锁与解锁。
    • QWaitCondition:提供了一种方法,使得线程可以在被另外线程唤醒之前一直休眠。

二、QThread的使用

1.QThread的创建与启动

  • 创建一个类继承QThread,并重写run函数。
  • 通过调用start函数启动线程,线程执行时会调用run函数。
  • 示例代码:

代码语言:txt
复制
#include <QThread>
#include <QDebug>
 
class MyThread : public QThread {
public:
    void run() override {
        qDebug() << "Running in background thread";
    }
};
 
int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);
    MyThread thread;
    thread.start();
    qDebug() << "Running in main thread";
    return a.exec();
}

2.线程的终止与销毁

  • 可以通过调用terminate函数强制终止线程,但这种方式不保证数据完整性和资源释放。
  • 使用wait函数可以阻塞调用的线程,直到其他线程执行完毕。
  • 动态分配的线程对象需要在合适的时候调用deleteLater销毁,防止内存泄漏。

3.线程间的通信

  • Qt的信号-槽机制支持跨线程通信。
  • 可以使用信号在一个线程中发射,在另一个线程中接收并处理。

三、线程同步

QMutex

  • QMutex用于保护共享资源,防止多个线程同时访问导致数据竞争。
  • 示例代码:

代码语言:txt
复制
#include <QCoreApplication>
#include <QThread>
#include <QDebug>
#include <QMutex>
 
QMutex mutex;
int sharedData = 0;
 
class MyThread : public QThread {
public:
    void run() override {
        mutex.lock();
        for (int i = 0; i < 10000; i++) {
            sharedData++;
        }
        mutex.unlock();
    }
};
 
int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);
    MyThread thread1;
    MyThread thread2;
    thread1.start();
    thread2.start();
    thread1.wait();
    thread2.wait();
    qDebug() << "sharedData: " << sharedData;
    return a.exec();
}

QSemaphore

  • QSemaphore允许指定一个资源的数量,线程可以通过获取和释放信号量来控制对资源的访问。
  • 示例代码:
代码语言:txt
复制
#include <QCoreApplication>
#include <QThread>
#include <QDebug>
#include <QSemaphore>
 
QSemaphore semaphore(1);
int sharedData = 0;
 
class MyThread : public QThread {
public:
    void run() override {
        semaphore.acquire();
        for (int i = 0; i < 10000; i++) {
            sharedData++;
        }
        semaphore.release();
    }
};
 
int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);
    MyThread thread1;
    MyThread thread2;
    thread1.start();
    thread2.start();
    thread1.wait();
    thread2.wait();
    qDebug() << "sharedData: " << sharedData;
    return a.exec();
}

QWaitCondition

  • QWaitCondition提供了一个条件变量,可以让线程在某个条件满足时等待,并在条件满足时被唤醒。
  • 示例代码:
代码语言:txt
复制
#include <QCoreApplication>
#include <QThread>
#include <QDebug>
#include <QWaitCondition>
#include <QMutex>
 
QWaitCondition condition;
QMutex mutex;
bool ready = false;
 
class MyThread : public QThread {
public:
    void run() override {
        mutex.lock();
        while (!ready) {
            condition.wait(&mutex);
        }
        qDebug() << "Thread is running";
        mutex.unlock();
    }
};
 
int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);
    MyThread thread;
    thread.start();
 
    QThread::sleep(2); // Simulate some work in the main thread
    mutex.lock();
    ready = true;
    condition.wakeAll();
    mutex.unlock();
 
    thread.wait();
    return a.exec();
}
四、示例:使用QThread实现耗时操作

设计思路

  • 创建一个工作线程类WorkThread,继承自QThread,并重写run函数,在其中执行耗时操作。
  • 在主线程中创建并启动工作线程,通过信号-槽机制在主线程中接收工作线程的状态变化。

代码实现

代码语言:txt
复制
#include <QCoreApplication>
#include <QThread>
#include <QDebug>
#include <QObject>
 
class WorkThread : public QThread {
    Q_OBJECT
public:
    void run() override {
        qDebug() << "WorkThread started";
        // Simulate a time-consuming operation
        for (int i = 0; i < 1000000000; i++) {
            // Do nothing, just waste time
        }
        qDebug() << "WorkThread finished";
        emit workFinished();
    }
 
signals:
    void workFinished();
};
 
int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);
 
    WorkThread workThread;
    QObject::connect(&workThread, &WorkThread::workFinished, &QCoreApplication::quit);
 
    workThread.start();
 
    int ret = a.exec();
    qDebug() << "Main thread finished with return code:" << ret;
    return ret;
}
 
#include "main.moc"

在这个示例中,WorkThread类继承自QThread,并重写了run函数来执行耗时操作。主线程中创建并启动了工作线程,并通过信号-槽机制在工作线程完成时退出主事件循环。

五、总结

多线程编程在提高程序响应速度和处理复杂任务时非常有用,但也需要小心处理线程间的同步和通信问题。Qt5提供了一套强大的多线程支持,通过QThread类及其相关类,开发者可以方便地实现多线程功能。希望这篇教程能帮助大家更好地理解和使用Qt5的多线程编程。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、线程基础
  • 二、QThread的使用
  • 三、线程同步
  • 四、示例:使用QThread实现耗时操作
  • 五、总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档