概述

Qt中有多种创建线程的方式,每一种的应用场景和使用方式都有些区别, 这里主要简单介绍Qt里面的几大创建线程的方法,以及使用注意事项。

QThread

使用QThread创建线程是我们最常见的一种方式,步骤如下:

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

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

#include <QThread>
#include <QDebug>class MyThread : public QThread
{Q_OBJECT
protected:void run(){//do somethingqDebug() <<__FUNCTION__ << "id = " << QThread::currentThreadId();QThread::msleep(1000);}
};
int main(int argc, char *argv[])
{QApplication a(argc, argv);qDebug() <<__FUNCTION__ << "id = " << QThread::currentThreadId();MyThread * myThread = new MyThread;myThread->start();return a.exec();
}

输出:

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

QRunnable

前面一篇文章已经详细介绍了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 Command : public QObject
{Q_OBJECT
public:explicit Command(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 "command.h"
#include <QDebug>Command::Command(QObject *parent) :QObject(parent)
{m_pThread = new QThread();this->moveToThread(m_pThread);connect(this,&Command::sigMsg,this,&Command::onMessage);m_pThread->start();qDebug()<< __FUNCTION__ << " id = "<< QThread::currentThreadId();
}void Command::sendMessage(const QString &msg)
{emit sigMsg(msg);
}void Command::onMessage(QString msg)
{qDebug()<< __FUNCTION__ << " id = "<< QThread::currentThreadId();
}

调用:

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

输出:

Command::Command  id =  0x4b58
Command::onMessage  id =  0x3c84

QtConcurrent::run

有关QtConcurrent::run的使用方法在之前的文章里面有详细介绍过,在这里,Concurrent是并发的意思,QtConcurrent是一个命名空间,提供了一些高级的 API,使得在编写多线程的时候,无需使用低级线程原语,如读写锁,等待条件或信号。使用QtConcurrent编写的程序会根据可用的处理器内核数自动调整使用的线程数。这意味着今后编写的应用程序将在未来部署在多核系统上时继续扩展。

QtConcurrent::run能够方便快捷的将任务丢到子线程中去执行,无需继承任何类,也不需要重写函数,使用非常简单。详见前面的文章介绍,这里不再赘述。

需要注意的是,由于该线程取自全局线程池QThreadPool,函数不能立马执行,需要等待线程可用时才会运行。

Qt中使用线程的几种方式及区别相关推荐

  1. Java并发基础01. 传统线程技术中创建线程的两种方式

    传统的线程技术中有两种创建线程的方式:一是继承Thread类,并重写run()方法:二是实现Runnable接口,覆盖接口中的run()方法,并把Runnable接口的实现扔给Thread.这两种方式 ...

  2. 【并发技术01】传统线程技术中创建线程的两种方式

    传统的线程技术中有两种创建线程的方式:一是继承 Thread 类,并重写 run() 方法:二是实现 Runnable 接口,覆盖接口中的 run() 方法,并把 Runnable 接口的实现扔给 T ...

  3. Java中创建线程的三种方式

    Java中创建线程主要有三种方式: 一.继承Thread类创建线程类 (1)继承Thread类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务.因此把run()方法称为执行体. ...

  4. java创建线程的两种方式及区别

    本文将介绍创建线程的两种方式,示例代码在下面,复制粘贴即可 继承Thread类方式和实现Runnable接口方式 区别:由于在开发的过程中,很多的类都会用到继承的方式,如果采用继承的方式会让各个类之间 ...

  5. 创建线程的三种方式及区别

    一:创建线程的三种方式: 1.继承Thread类 2.实现Runnable接口 3.使用Callable接口 二:创建线程的具体实现步骤: 1.继承Thread类 (1).先继承 Thread类,并且 ...

  6. java中创建线程的四种方式及线程池详解

    众所周知,我们在创建线程时有四种方法可以用,分别是: 1.继承Thread类创建线程 2.实现Runnable接口创建线程 3.使用Callable和Future创建线程 4.使用线程池创建(使用ja ...

  7. vue中data定义数字类型_[乐意黎原创] Vue中data定义的三种方式和区别

    在 Vue中,定义data时,经常有好几种写法,一不小心会混淆,这里彻底详述一下,以便记分清 . 一.在vue中,定义data可以有三种写法. 1. 第一种写法,data是一个对象. var app ...

  8. java中创建两种线程的方式_java中创建线程的两种方式有什么区别?

    *** 一.创建线程 1.继承Thread类 定义类继承Thread, 重写run()方法, 将线程中要执行的代码写在run()方法中 创建该类对象, 调用start()方法就可以开启一条新线程, 新 ...

  9. java创建线程几种_java中创建线程有几种方式

    详细内容 线程的创建方式 1.继承Thread类实现多线程 2.覆写Runnable()接口实现多线程,而后同样覆写run().推荐此方式 3.使用Callable和Future创建线程 相关视频教程 ...

最新文章

  1. java 正序a~z_Flutter MapString, dynamic 、ListString a-z 排序
  2. 阿里巴巴集团2014秋季校园招聘笔试题
  3. discuz数据库迁移,改密码后,相关配置文件修改
  4. python一到10整数的平方和_零基础学python_10_列表(创建数值列表 )
  5. 微服务的真相(一)服务拆的太小,后面迭代忍不了
  6. 外卖员不满上楼送餐要求向外卖吐口水4次,顾客不知情吃下整份外卖...
  7. 数据库lib7第2, 3题(创建索引和触发器)
  8. 机器学习基石12-Nonlinear Transformation
  9. js进阶 11-8 jquery如何获取元素相对于父元素的位置
  10. bootstrap tab 组合表头
  11. BI前端展示工具评估
  12. Atitit.使用引擎加脚本架构的设计 使用php,js来开发桌面程序。。
  13. jQuery WeUI 组件下拉刷新和滚动加载的实现(复制就可以使用)
  14. python开源项目之五子棋
  15. Shell及Linux三剑客grep、sed、awk
  16. Android蓝牙打印服务,Android 模拟蓝牙打印机
  17. 微型计算机最大的电路板是,微型计算机系统中最大的一块电路板被称作 。
  18. 软件测试-18个功能测试点总结
  19. Aaron Kwok
  20. MongoDB 启动参数

热门文章

  1. AI换脸引发全民恐慌,用对方向却能推动行业变革
  2. 新后缀勒索病毒.phobos 解密成功 sql数据恢复
  3. 总有人愿意为了你多做一些
  4. 基于深度前馈序列记忆网络,如何将语音合成速度提升四倍?
  5. JDK工具jstatd用法详解(转)
  6. ROI(投资回报率 Return On Investment)
  7. 判断scrollview是否滚动到了底部
  8. gSoap的“error LNK2001: 无法解析的外部符号 _namespaces”解决方法
  9. Python内建函数之——filter,map,reduce
  10. java异常处理图片_Java处理图片时出现异常