Qt·QThreadPool

本文介绍了Qt线程池QThreadPool。在资源密集型操作中,为提高效率诞生了线程池。Qt中用QRunnable统一封装任务,便于管理。线程池本质是协调任务和线程两种数据的交互。还阐述了QThreadPool的使用方法,包括线程池、线程、任务相关的函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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_OBJECT
public:
    WorkRunnable();
protected:
    void run();
signals:
    void result(const QString &str);
public slots:
    void doSomething(const QString &str);
}

采用这种方法需要注意一点,就是 QObject 必须放在 QRunnable 前面,列表初始化时也同样如此。

3. 线程池的本质是什么?

线程池这个概念不属于操作系统的范畴,存粹就是设计者自己写的一套管理工具。从感性的角度想,既然线程池称为“池子”,那这个“池子”里起码有「线程」和「任务」两种数据。因此 QThreadPool 类有着两种私有成员变量:QRunnable 和 QThread。但是为了便于管理很多的任务和线程,线程池将这两种数据进行了二次封装并用容器存储了起来,而线程池的本质就是协调两种容器之间数据的交

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

无用程序员~

家里还有病重的爷爷奶奶🙏🙏

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

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

打赏作者

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

抵扣说明:

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

余额充值