Qt中多线程使用方法

概述

Qt中有多种创建线程的方式,每一种的应用场景和使用方式都有些区别, Qt中线程的创建和使用,以及使用注意事项。
QThread

QThread步骤如下:

    继承QThread
    重写run()函数
    通过start()函数启动线程

优点:可以通过信号槽与外界进行通信。
缺点:1.每次新建一个线程都需要继承QThread,实现一个新类,使用不太方便。
2.要自己进行资源管理,线程释放和删除。并且频繁的创建和释放会带来比较大的内存开销。
适用场景:QThread适用于那些常驻内存的任务。

#include <QThread>
#include <QDebug>

class Thread : public QThread
{
    Q_OBJECT
protected:
    void run(){
        //do something
        qDebug() <<__FUNCTION__ << "id = " << QThread::currentThreadId();
        QThread::msleep(1000);
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    qDebug() <<__FUNCTION__ << "id = " << QThread::currentThreadId();

    Thread * myThread = new Thread;
    myThread->start();

    return a.exec();
}

输出:

main id =  0x29a4
Thread::run id =  0x1c2c

QRunnable
优缺点和适用场景。
步骤如下:

    继承QRunnable。和QThread使用一样, 首先需要将你的线程类继承于QRunnable。
    重写run函数。还是和QThread一样,需要重写run函数,run是一个纯虚函数,必须重写。
    使用QThreadPool启动线程

优点:无需手动释放资源,QThreadPool启动线程执行完成后会自动释放。
缺点:不能使用信号槽与外界通信。
适用场景:QRunnable适用于线程任务量比较大,需要频繁创建线程。QRunnable能有效减少内存开销。

moveToThread:
moveToThread是在QThread的用法基础上扩展出来的,它是QObject的接口,相对QThread线程方式来说,moveToThread使用更灵活,不需要继承QThread,也不用重写run函数。只需要将一个继承于QObject的类通过moveToThread移到QThread的一个对象中。
需要注意的是:

    只有在槽中执行的操作才是在线程中执行的,所以需要通过连接信号槽的方式来实现
    如果object对象存在父对象,不能将其移到子线程中执行。

示例如下:

#include <QObject>
#include <QThread>

class MyCommand : public QObject
{
    Q_OBJECT
public:
    explicit MyCommand (QObject *parent = nullptr);
    void sendMessage(const QString &msg);

signals:
    void sigMsg(QString msg);

private slots:
    void onMessage(QString msg);

private:
    QThread * m_pThread = nullptr;
};

#include "mycommand.h"
#include <QDebug>

MyCommand ::MyCommand(QObject *parent) :
    QObject(parent)
{
    m_pThread = new QThread();
    this->moveToThread(m_pThread);
    connect(this,&MyCommand::sigMsg,this,&MyCommand::onMessage);
    m_pThread->start();
    qDebug()<< __FUNCTION__ << " id = "<< QThread::currentThreadId();
}

void MyCommand::sendMessage(const QString &msg)
{
    emit sigMsg(msg);
}

void MyCommand::onMessage(QString msg)
{
    qDebug()<< __FUNCTION__ << " id = "<< QThread::currentThreadId();
}

调用:

m_pCommand = new MyCommand();   //不能指定父类
m_pCommand->sendMessage("ABC");

输出:

MyCommand::MyCommand  id =  0x4b58
MyCommand::onMessage  id =  0x3c84

Qt Concurrent的功能介绍

Qt在其QtConcurrent命名空间中为我们提供了编写多线程程序的高级API,使用这个API可以使我们在不使用低级的线程元素,如互斥锁,读写锁,条件变量或者信号量的情况下编写出搞笑的多线程程序。并且,使用QtConcurrent编写的程序能够自动地根据当前可以使用的处理器核心数调整实际使用的线程数目。这就意味着我们目前所写的程序即使将来的多核心机器上也能正常运行,并有很好的伸缩性。
#include <QCoreApplication>
#include <QtConcurrent>
#include <QDebug>

void func1()
{
    for(int i=0;i<1000;i++)
    {
           qDebug() << "Func 1 ouput" << i;
    }
};

void func2()
{
    for(int i=0;i<1000;i++)
    {
           qDebug() << "Func 2 ouput" << i;
    }
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QtConcurrent::run(func1);
    QtConcurrent::run(func2);

    return a.exec();
}


需要注意的是,由于该线程取自全局线程池QThreadPool,函数不能立马执行,需要等待线程可用时才会运行。
————————————————
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Pailugou

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值