qt非thread使用sleep_Qt 多线程编程之降低线程的开销

本文介绍了Qt线程池的使用,通过QRunnable实现任务封装,避免频繁创建和销毁线程导致的性能损耗。讨论了线程池的本质、任务与线程的管理,以及如何通过QThreadPool进行线程池操作,以提高资源利用效率,尤其适合资源密集型任务。文中提供了一系列相关函数的使用示例。
摘要由CSDN通过智能技术生成

本文结构如下:概述

任务的统一封装形式:QRunnable为什么要统一封装形式?

如何使用 QRunnable?

如何使用信号槽通信?

线程池的本质是什么?线程池中的两种数据之一:任务

线程池中的两种数据之一:线程

线程池如何处理这两种数据?

如何使用 QThreadPool线程池相关

线程相关

任务相关

附:所有函数

1. 概述

一般的多线程任务大多是避免主线程阻塞(界面卡死),开销线程的次数少。现在有一个光伏监控系统用于采集光伏板的发电功率,每次接收完网络数据包就会进行数据库的写操作。为了不占用主 GUI 线程,这一过程都在新线程里完成。但是成百上千的光伏板时时刻刻都会传送数据过来,如果每一次的执行都完整的创建线程-执行-销毁线程,可见这对于资源的消耗是何等之高。

根据《Qt 多线程编程之敲开 QThread 类的大门》中的「3.1 开多少个线程比较合适?」所讲“频繁的切换线程会使性能降低”,尤其是资源密集型操作,如需要 CPU 进行大量的运算任务。为了提高效率,在不增加资源(如 CPU 核数)的情况下,如何利用现有资源成了唯一的解决思路。线程池就是在这样的背景下诞生的。

2. 任务的统一封装形式:QRunnable

2.1 为什么要统一封装形式?

从直观的角度来看,线程池里有若干个线程,我们只要将执行的任务“扔”到这个“池子”里就可以了。在 Qt 中,所有需要线程池的任务都用 QRunnable 统一封装起来,为什么要这样做而不是类似 QObject::moveToThread() 的方式呢?其实这样做只是为了方便管理而已。上百个任务如果都是统一的类,那就可以用一个数组来管理了。

除此以外,能用到线程池的任务,基本上功能单一且并不需要和其他线程进行信号槽的通信。所以基于这样的场景,Qt 没有将 QRunnable 设计成 QObject 的子类,也是最大限度地精简“任务”负担。

2.2 如何使用 QRunnable?

QRunnable()

virtual ~QRunnable()

bool autoDelete() const

void setAutoDelete(bool autoDelete)

virtual void run() = 0

使用 QRunnable 非常简单,继承后重写 run() 函数,然后“扔”给线程池即可。成员函数也就 autoDelete() 这么一种,用于设置对象的所有权。默认设置为 true,线程结束后会自动删除该对象,也就是说扔到线程里就不用管何时去删除的问题了。简单的使用示例如下代码所示:

class HelloWorldTask : public QRunnable

{

void run() override

{

qDebug() << "Hello world";

}

};

HelloWorldTask *task = new HelloWorldTask();

QThreadPool::globalInstance->start(task);

2.3 如何使用信号槽通信?

因为 QRunnable 不是 QObject 的子类,因此不能使用信号槽这种元对象系统特性。如果使用场景需要信号槽通信,解决办法就是采用 QObject、QRunnable 双继承形式,例如下列代码:

class WorkRunnable : public QObject, public QRunnable

{

Q_OBJ

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值