QT学习之如何使用QThread(继承QThread)

概述

​ 通常在程序中需要同时做好几件事情,这时不可避免的会涉及到多线程的学习,QT学习过程中亦是如此,而QT中提供了 QThread,因为涉及到信号与槽,线程的使用也有些变化。在QThread的文档中有两种使用方法。

一. 继承 QThread

在第二种方式中,直接继承QThread 类,并且重新实现 run 函数,且只有run 函数就运行在新的线程中。所以常见的做法如下:

  • 继承 QThread 类;

  • 重新实现 run 函数,要在其中实现无限循环或者事件循环,线程才不会退出;

  • 代码片段如下:

    //Consumer 继承于 QThread
    Consumer consumer; 
    consumer.start(); //就是运行 run函数
    
注意:
  • 只有运行在 run 函数的代码,才在新的线程中

  • 如果别的线程和 run 函数中,同时操作线程对象(如 consumer)的成员变量,这个时候就要做线程同步,为其做加锁等操作!

二. 使用继承 QThread 类的例子

下面用一个简单的生产者-消费者例子来说明它的使用:

  1. 先创建一个生产者,简单的加一个生产完成信号
#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

  1. 再创建一个消费者线程,继承 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;

        }
    }

 }
  1. 在主函数中实现
#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();
}
  • 结果
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P8ycmNX1-1616430866671)(./image/QThread线程结果.png)]

从上面可以看出:

  • 该继承于 QThread 类的对象,只有run()运行在新的线程中,其他函数是在主线程中运行,因此这个时候如果对象的成员变量,同时在两个线程中被操作时,就要考虑线程同步的问题了
  • 就算是用信号发送的方式,Qthread对象 的槽函数也是运行于旧的线程

项目代码已上传,欢迎下载!
后续也将分享QT的学习,欢迎点赞,关注,赞赏我!

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_33974167

有价值,请赏瓶水喝

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值