概述
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,函数不能立马执行,需要等待线程可用时才会运行。
————————————————
Qt中多线程使用方法
最新推荐文章于 2024-05-21 12:44:55 发布