概述
通常在程序中需要同时做好几件事情,这时不可避免的会涉及到多线程的学习,QT学习过程中亦是如此,而QT
中提供了 QThread
,因为涉及到信号与槽,线程的使用也有些变化。在QThread
的文档中有两种使用方法。
文章目录- 概述
- 一. 继承 QThread 类
- 二. 使用继承 QThread 类的例子
一. 继承 QThread
类
在第二种方式中,直接继承QThread
类,并且重新实现 run
函数,且只有run
函数就运行在新的线程中。所以常见的做法如下:
1. 继承 QThread
类;
2. 重新实现 run
函数,要在其中实现无限循环或者事件循环,线程才不会退出;
3. 代码片段如下:
代码语言:javascript复制//Consumer 继承于 QThread
Consumer consumer;
consumer.start(); //就是运行 run函数
注意:
1. 只有运行在 run
函数的代码,才在新的线程中
2. 如果别的线程和 run
函数中,同时操作线程对象(如 consumer
)的成员变量,这个时候就要做线程同步,为其做加锁等操作!
二. 使用继承 QThread 类的例子
下面用一个简单的生产者-消费者例子来说明它的使用:
1. 先创建一个生产者,简单的加一个生产完成信号
代码语言:javascript复制#ifndef PRODUCER_H
#define PRODUCER_H
#include <QObject>
class Producer : public QObject
{
Q_OBJECT
public:
explicit Producer(QObject *parent = nullptr);
signals:
void produce(QString fruit); //生产水果完成信号
public slots:
};
#endif // PRODUCER_H
2. 再创建一个消费者线程,继承 QThread
类, 在线程中实现消费
- 在头文件中,声明
run
函数 以及接受来自生产者的槽函数
#ifndef CONSUMER_H
#define CONSUMER_H
#include <QThread>
#include <QQueue>
class Consumer : public QThread
{
Q_OBJECT
public:
Consumer();
private:
void run() override; //重新实现run()
QQueue<QString> fruits; //用于接收生产者生产的水果
public slots:
void get(const QString fruit); //接收水果的槽函数
};
#endif // CONSUMER_H
- 在源文件中,主要是在在
run
函数中,一直读取来自生产者发送来的数据
#include "consumer.h"
#include <QDebug>
Consumer::Consumer()
{
}
void Consumer::get(const QString fruit)
{
qDebug()<<"当前get()所在线程ID:"<<QThread::currentThreadId()<<endl;
fruits.enqueue(fruit);
}
void Consumer::run()
{
while(true)
{
if(fruits.size() > 0)
{
qDebug()<<"当前run()所在线程ID:"<<QThread::currentThreadId()<<endl;
qDebug()<<"我吃了一个:"<<fruits.dequeue()<<endl;
}
}
}
3. 在主函数中实现
代码语言:javascript复制#include <QCoreApplication>
#include <QDebug>
#include "producer.h"
#include "consumer.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qDebug()<<"当前consumer所在线程ID:"<<QThread::currentThreadId()<<endl;
Producer producer; //生产者
Consumer consumer; //消费者线程
QObject::connect(&producer,&Producer::produce,&consumer,&Consumer::get); //绑定生产者信号
consumer.start();
producer.produce("apple"); //生产苹果
producer.produce("banana"); //生产香蕉
return a.exec();
}
4. 结果
从上面可以看出:
- 该继承于
QThread
类的对象,只有run()运行在新的线程中,其他函数是在主线程中运行,因此这个时候如果对象的成员变量,同时在两个线程中被操作时,就要考虑线程同步的问题了 - 就算是用信号发送的方式,
Qthread对象
的槽函数也是运行于旧的线程