【Qt】Qt多线程开发 —【QThreadPool 】线程池

Qt多线程 — QThreadPool 线程池

一、简介

ThreadPool用于管理和回收单个QThread对象,目的是减少使用线程的应用程序中的创建线程的成本。每个Qt应用程序都包含一个全局的QThreadPool对象,可以调用globalInstance()来访问这个全局的QThreadPool对象。

二、使用方法

使用QThreadPool线程,需按照以下4个步骤:

(1)继承QRunnable。

(2)重载并实现run()虚函数。

(3)创建该类的一个对象。

(4)将创建的对象传递给QThreadPool::start()。

​ 例如以下代码片段:

//【1】继承QRunnable,定义MyTask类
class MyTask : public QRunnable
{
    //【2】重载并实现run()虚函数
    void run() override
    {
        qDebug() << "I'm iriczhao!!!" << QThread::currentThread();
    }
};

//【3】创建MyTask类的对象my_task
MyTask *my_task = new MyTask();
//【4】将创建的对象传递给QThreadPool::start
QThreadPool::globalInstance()->start(my_task);
三、QThreadPool的成员函数
(3-1)设置自动删除标志【setAutoDelete】

​ 默认情况下,QThreadPool会自动删除QRunnable。使用QRunnable::setAutoDelete()来更改自动删除标志。

​ 注意:这个标志必须在调用QThreadPool::start()之前设置。在QThreadPool::start()之后调用setAutoDelete函数将出现未定义的行为。

​ QThreadPool支持在QRunnable::run()中调用tryStart(this)来多次执行同一个QRunnable。如果autoDelete被启用,QRunnable将在最后一个线程退出run函数时被删除。在启用autoDelete条件下,使用同一个QRunnable对象多次调用start()会创建一个竞争条件(在开发中不建议这样使用)。

(3-2)设置线程超时时间【setExpiryTimeout】

​ 在一定时间内未使用的线程将过期(超时时间为30000毫秒(30秒)),Qt中使用expiryTimeout来描述该参数。这个参数可以使用setExpiryTimeout()函数更改。当超时时间设置为负数时将禁用线程过期机制。

​ 在expiryTimeout毫秒内未使用的线程被认为已经过期并将退出。这些线程将在需要时再重新启动。默认的expiryTimeout是30000毫秒(30秒)。如果expiryTimeout为负值,则新创建的线程不会过期,例如:在线程池销毁之前,线程不会退出。

(3-3)设置线程池的最大线程数【setMaxThreadCount】
  • 调用maxThreadCount()来查询线程池中使用的最大线程数。
  • 可以使用setMaxThreadCount()更改最大的线程数。默认maxThreadCount()是QThread::idealThreadCount()函数的结果。
  • 使用activeThreadCount()函数返回当前正在运行的线程数。注:该函数的返回值可能会大于最大线程数maxThreadCount
(3-4)预留线程【reserveThread】

​ 调用reserveThread()函数预留一个线程。如果一个线程运行完成,则可以调用releaseThread()允许它被重用。注意:这个函数会增加活动线程的数量。

void QThreadPool::reserveThread()
(3-5)释放线程【releaseThrad】

releaseThread()函数的作用是:释放使用reserveThread()预留的线程。

注意:如果调用此函数时,没有预先预留线程,则会临时增加maxThreadCount()。当一个线程进入休眠状态,等待更多工作时,此时使用该函数很有用,因为它允许其他线程继续工作。在使用中,需确保在完成等待后再调用reserveThread(),以便线程池能够正确维护活动线程的数量。

void QThreadPool::releaseThread()
(3-6)开始线程【start】

​ 开始线程池运行调度,在这种情况下,runnable被添加到运行队列中。priority参数可以用来控制运行队列的执行顺序。

void QThreadPool::start(QRunnable *runnable, int priority = 0)

​ 在Qt5.15版本后,支持运行一个函数:

void QThreadPool::start(std::function<void ()> functionToRun, int priority = 0)
(3-7)设置堆栈大小【setStackSize】

​ 该属性值仅在线程池创建新线程时使用。更改它对已经创建或正在运行的线程没有影响。默认值是0,这使得QThread使用操作系统的默认堆栈大小。

(3-8)清除线程池【clear】

​ 从队列中移除尚未启动的runnable。如果runnable->autoDelete()返回true,则runnable将被删除。

void QThreadPool::clear()
(3-9)等待执行完成【waitForDone】

​ 使用waitForDone设置线程超时等待时间。如果所有线程都被移除,则返回true;否则返回false。如果msecs为-1(默认值),则忽略超时(等待最后一个线程退出)。

bool QThreadPool::waitForDone(int msecs = -1)
四、使用示例
(4-1)定义runnable

​ 在以下代码中,将定义三个运行线程:MyTask0MyTask1MyTask2

class MyTask0 :public QRunnable
{
public:
     MyTask0(){}
    ~MyTask0()override
    {
        qDebug()<<"MyTask0 exit!!";
    }
protected:
    void run() override
    {
        qDebug() << "MyTask0" << QThread::currentThread();
    }

};


class MyTask1 :public QRunnable
{
public:
    MyTask1(){}
     ~MyTask1()override
    {
        qDebug()<<"MyTask1 exit!!";
    }
protected:
    void run() override
    {
            qDebug() << "MyTask1"<< QThread::currentThread();

    }

};


class MyTask2 :public QRunnable
{
public:
    MyTask2(){}
     ~MyTask2()override
    {
        qDebug()<<"MyTask2 exit!!";
    }
protected:
    void run() override
    {
            qDebug() << "MyTask2" << QThread::currentThread();
    }

};
(4-2)main函数
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
	
    //创建任务
    auto *Task0 = new MyTask0();
    auto *Task1 = new MyTask1();
    auto *Task2 = new MyTask2();
	
    //开始Task0
    QThreadPool::globalInstance()->start(Task0);
    QThreadPool::globalInstance()->waitForDone(-1);
	//开始Task1
    QThreadPool::globalInstance()->start(Task1);
    QThreadPool::globalInstance()->waitForDone(-1);
	//开始Task2
    QThreadPool::globalInstance()->start(Task2);
    QThreadPool::globalInstance()->waitForDone(-1);


    qDebug()<<"activeThreadCount"<<QThreadPool::globalInstance()->activeThreadCount()<<"maxThreadCount"			<<QThreadPool::globalInstance()->maxThreadCount();

    return 0;
}

​ 【输出结果】

MyTask0  QThreadPoolThread(0x312f3d0, name = "Thread (pooled)")
MyTask0 exit!!
    
MyTask1  QThreadPoolThread(0x312f5f0, name = "Thread (pooled)")
MyTask1 exit!!
    
MyTask2  QThreadPoolThread(0x312f510, name = "Thread (pooled)")
MyTask2 exit!!
    
activeThreadCount 0 maxThreadCount 8

扫一扫关注微信公众号,获取更多精彩内容>>>>
请添加图片描述

  • 5
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 3 和 TypeScript 的结合使用可以提供更好的类型检查和编辑器支持。下面是一些在 Vue 3 中使用 TypeScript 的常见用法和步骤: 1. 创建一个 Vue 3 项目,并选择 TypeScript。你可以使用 Vue CLI 或手动配置项目。 2. 在 Vue 组件中使用 TypeScript,可以通过以下几种方式: - 使用 `.vue` 后缀的单文件组件(SFC):在文件中添加 `<script lang="ts">` 标签,并编写 TypeScript 代码。 - 使用常规的 `.ts` 文件:在 `.ts` 文件中定义 Vue 组件,然后在 `.vue` 文件中导入并使用。 3. 在 Vue 组件中声明组件的类型和属性:可以使用 `defineComponent` 函数来声明 Vue 组件,通过泛型参数指定组件的 props 类型。 4. 使用 Composition API:Vue 3 引入了 Composition API,它可以更好地支持 TypeScript。你可以在组件中使用 `setup` 函数,并使用 `ref`、`reactive` 等函数创建响应式数据。 5. 在模板中使用 TypeScript 类型:可以使用 `<template>` 标签中的指令和插值表达式来访问组件的属性和方法。通过添加类型注解,可以在模板中获取类型检查和自动完成。 6. 使用 Vue Router 和 Vuex:如果你在项目中使用了 Vue Router 和 Vuex,你可以使用它们的 TypeScript 类型定义来获得更好的类型检查。 这些只是一些常见的用法,你可以根据具体的项目需求进一步探索 Vue 3 和 TypeScript 的使用方式。希望这些信息对你有所帮助!如果你有其他问题,可以继续提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值