Qt中多线程相关的类
QThread | QThread类是Qt中用于创建和管理线程的基类。通过继承QThread类并重写其中run()函数,可以定义自己的线程类。 |
QMutex | QMutex类是Qt中用于实现线程间互斥访问的类。它可以用于保护共享资源,避免多个线程同时访问导致的竞争问题。 |
QMutexLocker | QMutexLocker类是Qt中用于自动管理互斥锁的类。它可以在作用域结束时自动释放互斥锁,避免忘记手动释放锁导致的问题。 |
QWaitCondition | QWaitCondition类是Qt中用于线程间等待和唤醒的类。它可以用于实现线程间的同步和通信。 |
QThreadPool | QThreadPool类是Qt中用于管理线程池的类。线程池可以用于管理多个线程的执行,提高线程的复用性和效率。 |
QRunnable | QRunnable类是Qt中用于表示可执行任务的类。通过继承QRunnable类并实现其中run()函数,可以定义自己的可执行任务。 |
QThread使用
QThread有两种使用方式:
继承QThread 重写 run()方法 | QThread是Qt提供的一个线程类,可以用于创建和管理线程。它是QObject的子类,提供了一些方便的方法来控制线程的执行。通过继承QThread类并重写run()方法,可以在一个独立的线程中执行自定义代码。使用QThread可以实现线程的创建、启动、中断、等待等操作。 |
QObject::moveToThread() | QObject::moveToThread()是QObject类的成员函数,用于将一个QObject对象移动到另一个线程中执行。当一个QObject对象被移动到一个新的线程时,它的事件循环会在新线程中启动,从而使得该对象的信号和槽以及其他事件能够在新线程中得到处理。 |
继承QThread重写run()函数方式
#include <QThread>
#include <QDebug>
// 自定义的工作线程类
class WorkerThread : public QThread{
Q_OBJECT
public:
void run() override{
qDebug() << "Worker thread ID: " << QThread::currentThreadId();
// 执行一些耗时的操作
for (int i = 0; i < 5; ++i){
qDebug() << "Working... " << i;
sleep(1);
}
}
};
int main(int argc, char *argv[]){
QCoreApplication app(argc, argv);
qDebug() << "Main thread ID: " << QThread::currentThreadId();
WorkerThread workerThread;// 创建工作线程
workerThread.start();// 启动工作线程
workerThread.wait();// 等待工作线程完成
qDebug() << "Worker thread finished.";// 输出工作线程结束后的提示信息
return app.exec();
}
可以在自定义的工作线程类的构造函数中添加:
connect(this,&QThread::finished,[this](){deletelater();});
该行代码是在线程结束后,自动销毁此线程。
QObject::moveToThread()方式
#include <QThread>
#include <QObject>
#include <QDebug>
// 自定义的工作类
class Worker : public QObject{
Q_OBJECT
public slots:
// 执行工作任务
void doWork(){
qDebug() << "Worker thread ID: " << QThread::currentThreadId();
for (int i = 0; i < 5; ++i){
qDebug() << "Working... " << i;
QThread::sleep(1);
}
emit workFinished();// 发送工作完成信号
}
signals:
void workFinished();
};
int main(int argc, char *argv[]){
QCoreApplication app(argc, argv);
qDebug() << "Main thread ID: " << QThread::currentThreadId();
Worker worker;// 创建工作对象
QThread workerThread;// 创建工作线程
worker.moveToThread(&workerThread);// 将工作对象移动到工作线程中
QObject::connect(&worker, &Worker::workFinished, &app, &QCoreApplication::quit);// 连接工作完成信号
workerThread.start();// 启动工作线程
QMetaObject::invokeMethod(&worker, "doWork", Qt::QueuedConnection);// 在工作线程中执行工作
return app.exec();// 运行主线程事件循环
}
QMutex
#include <QCoreApplication>
#include <QMutex>
#include <QThread>
#include <QDebug>
QMutex mutex; // 创建一个互斥锁对象
class Worker : public QObject
{
Q_OBJECT
public slots:
void doWork(){
mutex.lock(); // 锁定互斥锁
qDebug() << "Worker thread ID: " << QThread::currentThreadId();
for (int i = 0; i < 5; ++i){
qDebug() << "Working... " << i;
QThread::sleep(1);
}
mutex.unlock(); // 解锁互斥锁
}
};
int main(int argc, char *argv[]){
QCoreApplication app(argc, argv);
qDebug() << "Main thread ID: " << QThread::currentThreadId();
Worker worker;
QThread workerThread;
worker.moveToThread(&workerThread);
QObject::connect(&workerThread, &QThread::started, &worker, &Worker::doWork);
QObject::connect(&worker, &Worker::finished, &app, &QCoreApplication::quit);
workerThread.start();
return app.exec();
}
QMutexLocker
#include <QCoreApplication>
#include <QMutex>
#include <QThread>
#include <QDebug>
QMutex mutex; // 创建一个互斥锁对象
class Worker : public QObject{
Q_OBJECT
public slots:
void doWork(){
QMutexLocker locker(&mutex); // 创建一个QMutexLocker对象,在构造函数中锁定互斥锁
qDebug() << "Worker thread ID: " << QThread::currentThreadId();
for (int i = 0; i < 5; ++i){
qDebug() << "Working... " << i;
QThread::sleep(1);
}
// QMutexLocker对象的析构函数会自动解锁互斥锁,无需手动调用mutex.unlock()
}
};
int main(int argc, char *argv[]){
QCoreApplication app(argc, argv);
qDebug() << "Main thread ID: " << QThread::currentThreadId();
Worker worker;
QThread workerThread;
worker.moveToThread(&workerThread);
QObject::connect(&workerThread, &QThread::started, &worker, &Worker::doWork);
QObject::connect(&worker, &Worker::finished, &app, &QCoreApplication::quit);
workerThread.start();
return app.exec();
}
QWaitCondition
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
#include <QDebug>
// 全局互斥量和条件变量
QMutex mutex;
QWaitCondition condition;
// 消费者线程类
class ConsumerThread : public QThread{
public:
void run(){
QMutexLocker locker(&mutex);
qDebug() << "Consumer: Waiting for data...";
// 当没有数据时等待条件变量被唤醒
condition.wait(&mutex);
qDebug() << "Consumer: Data received!";
}
};
// 生产者线程类
class ProducerThread : public QThread{
public:
void run(){
QThread::sleep(2); // 模拟生产数据的耗时操作
QMutexLocker locker(&mutex);
qDebug() << "Producer: Sending data...";
// 发送信号给消费者线程,唤醒它继续执行
condition.wakeOne();
qDebug() << "Producer: Data sent!";
}
};
int main(){
ConsumerThread consumerThread;
ProducerThread producerThread;
// 启动消费者线程
consumerThread.start();
// 启动生产者线程
producerThread.start();
// 等待线程结束
consumerThread.wait();
producerThread.wait();
return 0;
}
QRunnable和QThreadPool
#include <QCoreApplication>
#include <QRunnable>
#include <QDebug>
#include <QThreadPool>
// 自定义任务类
class MyTask : public QRunnable{
public:
void run(){
qDebug() << "Task started in thread" << QThread::currentThread();
// 模拟耗时操作
for (int i = 0; i < 100000000; ++i) {
// do something
}
qDebug() << "Task finished in thread" << QThread::currentThread();
}
};
int main(int argc, char *argv[]){
QCoreApplication a(argc, argv);
// 创建线程池
QThreadPool threadPool;
// 设置最大线程数
threadPool.setMaxThreadCount(4);
// 创建并提交任务
for (int i = 0; i < 10; ++i) {
MyTask *task = new MyTask();
threadPool.start(task);
}
// 等待所有任务完成
threadPool.waitForDone();
return a.exec();
}
注意:QRunnable和QThread很相像,都有一个run函数,在run函数为在线程内执行的代码。但是不同的是,QRunnable本身并不创建一个新线程,它需要与QThreadPool线程池一起使用。