【QT】- QThread类介绍和线程的创建
QThread 是 Qt 自带的类,它用于在 Qt 中实现多线程编程。QThread 类提供了一个简单的接口来启动和管理线程,它封装了操作系统级的线程管理机制,使得开发者可以更容易地创建、管理和控制线程。
QThread 类概述
QThread 是 Qt 的线程类,它为你提供了线程管理的基本功能,包括线程的启动、终止、同步等。通过继承 QThread 类或者使用线程池,你可以在 Qt 中方便地实现多线程操作。
主要功能
创建线程:QThread 提供了启动线程的方法,如 start()。
线程执行:线程执行时,run() 函数会被调用,你可以在这个函数中编写你希望在线程中执行的任务。
线程管理:通过 wait()、terminate() 等函数,管理线程的生命周期。
线程同步:通过信号与槽机制或使用锁等同步方法,可以进行线程间的通信和同步。
如何使用 QThread?
QThread 的使用通常有两种常见方式:
继承 QThread 并重写 run() 方法:
通过继承 QThread 类,并重写 run() 方法来定义线程执行的任务。
这种方式适用于你希望线程执行某个具体任务并在其生命周期中管理该任务的场景。
将任务移到单独的对象中并通过信号与槽机制控制线程:
你可以将要执行的任务放在一个普通的对象中,而不直接重写 run()。然后通过信号和槽机制在主线程和子线程之间传递数据或控制线程。
这种方式更符合 Qt 的设计哲学,使得线程与任务解耦。
下面将通过代码示例详细讲解这两种方式。
示例 1:继承 QThread 并重写 run() 方法
这种方法是最常见的用法,适合需要在线程中执行某个特定任务的场景。你只需要继承 QThread 并重写 run() 方法,然后调用 start() 启动线程。
cpp
#include <QCoreApplication>
#include <QThread>
#include <QDebug>
class MyThread : public QThread {
protected:
void run() override {
// 这里是线程执行的代码
for (int i = 0; i < 5; ++i) {
qDebug() << "Running in thread:" << QThread::currentThreadId() << ", step:" << i;
QThread::sleep(1); // 模拟任务
}
}
};
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
// 创建线程对象
MyThread thread;
thread.start(); // 启动线程
// 等待线程完成
thread.wait();
return a.exec();
}
解释:
继承 QThread:MyThread 继承了 QThread,并且重写了 run() 方法。run() 方法是在线程中执行的任务,我们在其中打印信息并使用 QThread::sleep(1) 来模拟任务。
启动线程:在 main() 函数中,调用 thread.start() 启动线程。此时会调用 run() 方法并执行线程任务。
等待线程结束:thread.wait() 会让主线程等待子线程执行完毕后再继续。wait() 是一个阻塞调用,它会阻塞主线程,直到子线程执行完毕。
示例 2:不继承 QThread,使用信号与槽来控制线程
另一种方式是将任务封装在一个普通对象中,不直接继承 QThread,而是通过信号与槽来在线程中执行任务。这种方法可以使代码更加灵活和解耦。
cpp
#include <QCoreApplication>
#include <QThread>
#include <QDebug>
class Worker : public QObject {
Q_OBJECT
public slots:
void doWork() {
// 这里是线程执行的任务
for (int i = 0; i < 5; ++i) {
qDebug() << "Running in thread:" << QThread::currentThreadId() << ", step:" << i;
QThread::sleep(1); // 模拟任务
}
}
};
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
// 创建工作对象
Worker worker;
// 创建线程对象
QThread thread;
// 将工作对象移到线程中
worker.moveToThread(&thread);
// 连接信号与槽
QObject::connect(&thread, &QThread::started, &worker, &Worker::doWork);
QObject::connect(&worker, &Worker::doWork, &thread, &QThread::quit);
// 启动线程
thread.start();
// 等待线程完成
thread.wait();
return a.exec();
}
解释:
创建 Worker 类:Worker 类中定义了一个槽函数 doWork(),它执行你希望在线程中完成的任务。
将 Worker 对象移到线程中:worker.moveToThread(&thread) 将工作对象 worker 移到 thread 所代表的线程中。此时,worker 中的槽函数 doWork() 会在新线程中执行。
连接信号与槽:通过 QObject::connect() 连接信号与槽。当线程 thread 启动时,会触发 started 信号,从而调用 worker 的 doWork() 槽函数。
启动线程并等待结束:通过 thread.start() 启动线程,然后使用 thread.wait() 等待线程完成。
QThread 的常用成员函数
start():
启动线程的执行,相当于调用操作系统级别的线程创建和执行。
run():
这是 QThread 中的虚拟函数,需要在子类中重写。run() 方法定义了线程执行的任务。
wait():
阻塞调用,等待线程执行完毕。如果主线程调用了线程对象的 wait(),则主线程会一直等待,直到该线程执行完成。
terminate():
强制结束线程的执行,但这个方法并不推荐使用,因为它没有清理资源的机会,可能导致资源泄漏。
quit():
退出线程的事件循环。通常在事件驱动的线程中使用,确保线程能够优雅地退出。
isRunning():
判断线程是否正在运行。
总结
QThread 是 Qt 提供的一个类,专门用于线程的管理。
你可以通过继承 QThread 并重写 run() 方法来实现多线程任务,也可以通过将任务移到一个 QObject 对象中,并通过信号与槽机制来实现多线程任务。
通过 start() 启动线程,wait() 等待线程执行完毕,terminate() 用于强制停止线程(不推荐使用)。