Qt 中的线程池QRunnable和QThreadPool

Qt 中的线程池QRunnable和QThreadPool

一、QThreadPool类介绍

QThreadPool 是 Qt 框架中用于管理线程池的类,它提供了一种高效的方式来管理和复用线程,避免频繁创建和销毁线程带来的开销。

1. 基本概念

QThreadPool 是一个全局的线程池,它维护了一组线程,并将任务分配给这些线程执行。线程池中的线程数量可以通过设置最大线程数来控制。当线程池中的线程被占用时,新任务会被排队等待执行。

2. 创建和使用线程池

Qt 提供了一个全局线程池 QThreadPool::globalInstance(),可以直接使用,也可以创建自己的线程池实例。

全局线程池的使用:

c++ 复制代码
// 获取全局线程池
QThreadPool *threadPool = QThreadPool::globalInstance();
// 设置最大线程数(可选)
threadPool->setMaxThreadCount(4);

自定义线程池的使用:

c++ 复制代码
QThreadPool *myThreadPool = new QThreadPool();
myThreadPool->setMaxThreadCount(8); // 设置最大线程数

3. 关键方法

以下是 QThreadPool 的一些常用方法:

(1) 设置线程池的最大线程数
c++ 复制代码
void QThreadPool::setMaxThreadCount(int maxThreadCount);

用于设置线程池中允许的最大线程数。默认值通常是系统核心数的两倍。

(2) 启动任务
c++ 复制代码
void QThreadPool::start(QRunnable *runnable);

将一个 QRunnable 对象提交到线程池中执行。

(3) 等待所有任务完成
c++ 复制代码
void QThreadPool::waitForDone();

阻塞当前线程,直到线程池中的所有任务都完成。

(4) 获取全局线程池
c++ 复制代码
static QThreadPool *QThreadPool::globalInstance();

返回全局线程池实例,通常用于共享程线池。

4. 注意事项

  1. 线程安全QThreadPool 是线程安全的,可以在多个线程中同时调用其方法。
  2. 任务的生命周期 :任务对象(QRunnable 的子类)通常由线程池管理,任务完成后会被自动删除。如果需要手动管理任务对象的生命周期,可以在任务类中重写 autoDelete() 方法。
  3. 任务队列:当线程池中的线程被占用时,新任务会被放入队列中等待执行。
  4. 线程池的销毁:当线程池被销毁时,所有未完成的任务会被取消,线程池中的线程也会被销毁。

二、QRunnable类介绍

QRunnable 是 Qt 框架中用于表示可运行任务的类,它是线程池(QThreadPool)中任务的接口。通过继承 QRunnable 并重写其 run() 方法,可以创建一个可以在单独线程中执行的任务。QRunnable 是 Qt 实现线程池任务调度的核心机制之一。

1. QRunnable 的作用

QRunnable 是一个抽象类,用于表示一个可以被线程执行的任务。它的主要目的是将任务封装为一个对象,然后通过线程池(QThreadPool)或其他线程管理机制来执行这些任务。QRunnable 的设计使得任务的创建和执行解耦,从而提高了代码的可维护性和可扩展性。

2. QRunnable 的基本用法

要使用 QRunnable,通常需要执行以下步骤:

1继承 QRunnable :创建一个继承自 QRunnable 的类。

2.重写 run() 方法 :在 run() 方法中实现任务的逻辑。

3.提交任务到线程池 :通过 QThreadPoolstart() 方法将任务提交到线程池中执行。

3. QRunnable 的关键特性

(1) 自动删除

QRunnable 提供了一个 autoDelete() 方法,用于控制任务对象在执行完成后是否自动删除。默认情况下,autoDelete() 返回 true,表示任务对象会在执行完成后自动删除。如果需要手动管理任务对象的生命周期,可以在任务类中重写 autoDelete() 方法。

c++ 复制代码
bool QRunnable::autoDelete() const;
(2) 设置优先级

QRunnable 允许设置任务的优先级,优先级高的任务会优先执行。

C++ 复制代码
void QRunnable::setAutoDelete(bool autoDelete);
void QRunnable::setPriority(QThread::Priority priority);
(3) 线程安全

QRunnable 是线程安全的,可以在多个线程中同时创建和提交任务。

4. QRunnable 的应用场景

QRunnable 适用于以下场景:

1.并发任务 :需要在多个线程中并发执行任务时,QRunnable 是一个很好的选择。

2.线程池管理 :通过 QThreadPoolQRunnable,可以高效地管理线程池中的任务,避免频繁创建和销毁线程。

3.简化线程管理QRunnable 将任务封装为对象,使得任务的创建和执行更加清晰和易于管理。

5. QRunnable 和 QThread 的区别

虽然 QRunnableQThread 都可以用于多线程编程,但它们的用途和设计目标有所不同:

  • QThread
    • 是一个完整的线程类,提供了对线程生命周期的精细控制。
    • 适用于需要长期运行的线程,或者需要手动管理线程生命周期的场景。
    • 使用起来相对复杂,需要手动启动和停止线程。
  • QRunnable
    • 是一个任务类,用于表示一个可以在单独线程中执行的任务。
    • 通常与 QThreadPool 配合使用,适用于短时间任务的并发执行。
    • 使用起来相对简单,任务完成后会自动删除。

三、使用示例

下面通过一个代码示例来讲述如何使用:

C++ 复制代码
#include <QCoreApplication>
#include <QThreadPool>
#include <QRunnable>
#include <QThread>
#include <QDebug>

class QMyTask:public QRunnable
{
public:
    QMyTask(int nID)
    {
        m_nID = nID;
    }

    ~QMyTask(){};

    virtual void run() override
    {
        qDebug() << "Task"<< m_nID << "Is Run On Thread" << QThread::currentThreadId();
        QThread::sleep(2); // 模拟耗时任务
        qDebug() << "Task" << m_nID << "finished";
    }

private:
    int m_nID;
};


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    
    QThreadPool* pThreadPool = QThreadPool::globalInstance();
    pThreadPool->setMaxThreadCount(4);

    for(int i=0;i<10;i++)
    {
        QMyTask* pTask = new QMyTask(i);
        pThreadPool->start(pTask);
    }

    pThreadPool->waitForDone();

    qDebug() << "All tasks are done.";


    return a.exec();
}

代码运行结果:

四、总结

1.QThreadPool 提供了一种简单而高效的方式来管理线程,特别适合处理大量短时间任务的场景。通过合理设置线程池的大小和任务的管理方式,可以显著提高程序的性能和响应速度。

2.QRunnable 是 Qt 中用于表示可运行任务的类,它通过线程池(QThreadPool)实现任务的并发执行。通过继承 QRunnable 并重写 run() 方法,可以轻松创建和管理任务。QRunnable 的设计使得任务的创建和执行解耦,提高了代码的可维护性和可扩展性。在需要并发执行短时间任务时,QRunnable 是一个非常高效的选择。

参考文章:

1.QT线程池的使用:QThreadPool类和QRunnable类

相关推荐
初阳7851 小时前
【Qt】系统相关(3)——多线程
qt
初阳7853 小时前
【Qt】系统相关(2)——文件
开发语言·qt
尘中远17 小时前
【Qwt 7.0 系列】坐标轴与刻度系统 —— 刻度引擎、网格、图例与刻度朝内
qt·数据可视化·qcustomplot·qwt·工业软件·科学绘图
sycmancia19 小时前
Qt——多线程间的互斥
开发语言·qt
尘中远1 天前
【Qwt 7.0 系列】常用图表类型实战 —— 柱状图、散点图、箱线图与直方图
qt·qwt·工业软件·科学绘图
尘中远1 天前
【Qwt 7.0 系列】交互功能详解 —— 平移、缩放、坐标轴交互与数据拾取
qt·数据可视化·绘图·qcustomplot·qwt·科学绘图
sycmancia1 天前
Qt——进程与线程的概念
qt
郝学胜-神的一滴1 天前
Qt 高级编程 034:深耕QWidget底层内核—彻底吃透无边框窗口设计核心原理
开发语言·c++·qt·程序人生·软件开发·用户界面
尘中远1 天前
【Qwt 7.0 系列】3D 数据可视化 —— OpenGL 高性能三维绘图
qt·3d·qcustomplot·qwt·科学绘图·高性能绘图
满天星83035771 天前
【Qt】控件(二) (geometry及与frameGeometry的区别)
开发语言·qt