Qt的多线程机制允许开发者在单个应用程序进程中创建并行任务,从而实现高效的资源利用和流畅的用户体验。
QThread 类来实现跨平台的多线程功能。QThread 对象代表一个操作系统级别的线程。QThread 对象的子类中覆盖 run() 函数并在其中执行长耗时任务;而是应该创建一个工作类,继承自 QObject,并在线程中移动这个工作对象,使其在新线程的事件循环中执行任务。头文件
#include
所属模块:
QT += core
QThread 对象,创建一个要在新线程上执行任务的工作类实例,并将该工作类移动到新线程中。QThread::start() 方法启动线程,这会触发 QThread 对象的 run() 函数,但在现代Qt实践下,run() 函数主要用于启动事件循环而非执行具体业务逻辑。moveToThread() 函数将一个QObject移动到另一个线程中后,其发出的信号会在目标线程的事件循环中排队,通过连接信号到槽,可以在不同线程之间安全地传递数据和控制流。// Worker.h
#include
class Worker : public QObject
{
Q_OBJECT
public:
using QObject::QObject;
public slots:
void doWork() {
// 这里放置你要在新线程中执行的具体任务
for (int i = 0; i < 1000000; ++i) {
// 假设这是一个耗时的操作
// ...
qDebug() << "Working in thread:" << QThread::currentThreadId();
}
emit workFinished();
}
signals:
void workFinished();
};
// 主程序
#include
#include
#include "Worker.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
// 创建QThread对象
QThread workerThread;
// 创建Worker对象
Worker worker;
// 将Worker对象移动到新线程中
worker.moveToThread(&workerThread);
// 连接信号槽,当线程开始运行时,执行doWork()
connect(&workerThread, &QThread::started, &worker, &Worker::doWork);
// 当Worker完成任务时,退出线程
connect(&worker, &Worker::workFinished, &workerThread, &QThread::quit);
// 当线程结束时,删除Worker对象
connect(&workerThread, &QThread::finished, &worker, &QObject::deleteLater);
// 启动线程
workerThread.start();
// 等待线程结束
workerThread.wait();
return a.exec();
}
在这个例子中,我们创建了一个Worker类,其中doWork槽函数包含我们要在新线程中执行的实际任务。我们将Worker对象移动到新创建的QThread中,并通过信号槽机制连接QThread::started信号和Worker::doWork槽函数。
当调用workerThread.start()时,新线程的事件循环开始运行,进而触发Worker::doWork方法执行。
注意,这里并没有直接在QThread的子类中重写run()函数来执行任务。
QMutex、QWaitCondition、QSemaphore 和 QReadWriteLock 等,用于解决多线程环境下的数据竞争和同步问题。#include
#include
#include
#include
class WorkerThread : public QThread
{
Q_OBJECT
public:
WorkerThread(QMutex* mutex, QWaitCondition* condition)
: m_mutex(mutex), m_condition(condition) {}
protected:
void run() override
{
while (!shouldStop()) {
// 请求资源
m_mutex->lock();
// 检查是否可以继续工作(此处仅为示例,实际场景可能更为复杂)
if (canProceed()) {
processData();
emit dataProcessed();
} else {
// 如果不能继续,则等待条件满足
m_condition->wait(m_mutex);
}
// 释放资源
m_mutex->unlock();
}
}
private:
bool canProceed() const { /* 实现检查条件的方法 */ }
void processData() { /* 执行需要同步的耗时操作 */ }
bool shouldStop() const { /* 检查是否需要停止线程 */ }
signals:
void dataProcessed();
private:
QMutex* m_mutex;
QWaitCondition* m_condition;
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QMutex mutex;
QWaitCondition condition;
WorkerThread worker(&mutex, &condition);
connect(&worker, &WorkerThread::dataProcessed, [](){
qDebug() << "Data processed!";
});
worker.start();
// 假设主线程在某一时刻改变了条件
// ...
mutex.lock();
// 更新状态或数据
condition.wakeOne(); // 唤醒等待的worker线程
mutex.unlock();
// 在适当时候停止worker线程...
return app.exec();
}
在这个例子中,WorkerThread类在一个循环中尝试获取互斥锁(QMutex),然后检查是否可以执行任务。如果条件不允许(例如,数据还没有准备好),则调用m_condition->wait(m_mutex),这会使线程进入等待状态,直到收到信(wakeOne()或wakeAll())告知条件已改变。
主线程可以通过锁定互斥锁,更新相关状态或数据,然后唤醒等待的线程,这样就实现了线程间的同步。当worker线程被唤醒后,会重新检查条件并执行相应任务。通过这种方式,可以有效地避免数据竞争问题,并确保线程在合适的时候执行操作。
QThread 类,而是将要并发执行的任务封装到一个单独的QObject派生类中,让QThread负责运行这些对象的事件循环。