Qt中的线程池

Qt中的线程池


目录

1 为什么需要线程池
2 Qt中有哪些方式实现线程池
3 如何通过QThreadPool类实现线程池
4 如何通过QtConcurrent库实现线程池
5 如何通过自定义的方式实现线程池
5 小结


1 为什么需要线程池

线程池是多线程编程中常用的一种技术,可以帮助管理系统中的线程资源、提高程序的性能、帮助控制并发度、简化多线程编程、提高程序的稳定性。所以,线程池在Qt开发中具有重要的作用,在需要进行多线程编程的场景下,使用线程池是一个常见且有效的选择。

    创建和销毁线程是有开销的,过多地创建线程可能会导致系统资源的浪费。通过使用线程池,可以预先创建一定数量的线程,并重复使用它们来执行任务,避免频繁创建和销毁线程,从而减少了资源开销。
    当有大量的任务需要执行时,线程池可以自动调度和分配任务给空闲的线程,实现并行执行,从而加快任务的处理速度。通过合理设置线程池的大小,可以充分利用系统资源,提高程序的响应性和吞吐量。
    通过限制线程池的最大线程数,可以控制并发执行的任务数量,避免资源竞争和过度消耗系统资源。
    线程池隐藏了线程的创建和管理细节,开发人员只需关注任务的实现,通过将任务提交给线程池,线程池会自动处理线程的创建、任务的调度和执行,减少了编程的复杂性。
    线程池可以限制同时执行的线程数量,避免过多的线程导致系统资源不足或崩溃。此外,线程池还可以处理异常情况,例如线程崩溃或异常退出时,线程池可以自动重新创建新的线程,保持系统的稳定运行。


2 Qt中有哪些方式实现线程池

1、Qt提供的QThreadPool线程池类,可以方便地管理和调度线程。

    2、Qt提供的QtConcurrent并行编程框架库,可以简化多线程编程,实现线程池。
    3、可以通过自己实现继承自QObject的线程池类,来实现更高级的线程池功能。


3 如何通过QThreadPool类实现线程池

在具体的操作上,通过QThreadPool类实现线程池,要经过如下步骤:

        1、创建一个继承自QRunnable的任务类,重写其run()函数,在其中实现任务的逻辑。

class MyTask : public QRunnable {
public:void run() {// 执行任务的逻辑}
};

        2、使用QThreadPool的globalInstance()静态函数来获取全局的线程池实例,并将任务对象添加到线程池中。

QThreadPool::globalInstance()->start(new MyTask());

        3、使用setMaxThreadCount()函数来设置线程池的最大线程数,控制并发执行的线程数量。

QThreadPool::globalInstance()->setMaxThreadCount(5);

        4、调用waitForDone()函数,等待线程池中的任务执行完成。

QThreadPool::globalInstance()->waitForDone();

    使用QThreadPool实现线程池功能时,QThreadPool会自动管理线程的创建、销毁和任务的调度,只需要关注任务的实现和提交,无需手动处理线程的创建和管理细节;通过合理设置线程池的最大线程数,可以控制并发执行的线程数量,从而优化性能和资源利用。

    需要注意的是,QThreadPool默认使用自动删除的方式来管理任务对象的内存(即任务执行完成后会自动删除任务对象)。如果需要手动管理任务对象的内存,可以通过调用setAutoDelete(false)来禁用自动删除,并在任务执行完成后手动删除任务对象。

    QThreadPool还提供了其他一些函数和信号,用于查询线程池的状态、取消任务、暂停和恢复线程池等操作;可以根据具体需求使用这些功能来实现更复杂的线程池逻辑。


4 如何通过QtConcurrent库实现线程池

在具体的操作上,通过QtConcurrent库实现线程池,要经过如下步骤:

        1、创建一个函数或Lambda表达式,用于执行任务的逻辑。该函数或Lambda表达式的参数和返回值类型根据任务的需求而定。

void myTask(int param) {// 执行任务的逻辑
}

        2、使用QtConcurrent::run()函数将任务提交给线程池执行。该函数会自动创建线程池,并将任务添加到线程池中;可以通过指定函数或Lambda表达式和参数来提交任务。

QtConcurrent::run(myTask, 42);

        3、使用QThreadPool的globalInstance()函数获取全局的线程池实例,并使用setMaxThreadCount()函数来设置线程池的最大线程数。

QThreadPool::globalInstance()->setMaxThreadCount(5);

        4、使用QThreadPool的waitForDone()函数来等待所有任务完成。

QThreadPool::globalInstance()->waitForDone();
QtConcurrent库会自动管理线程的创建、销毁和任务的调度,只需关注任务的实现和提交,无需手动处理线程的创建和管理细节。使用QtConcurrent库可以方便地实现并行执行任务,提高程序的性能和响应性。

    QtConcurrent库还提供了其他一些函数和类,用于执行更复杂的并行任务,例如map、filter、reduce等操作。这些函数和类可以进一步简化并行任务的编写和管理。可以根据具体需求选择合适的函数和类来实现线程池的功能。


5 如何通过自定义的方式实现线程池

通过继承QThread的线程类,在该线程类的run()函数中循环来等待目标任务的到来并执行任务,就可以实现一个自定义的线程池。     在具体的操作上,通常要经过如下步骤:

        1、创建一个继承自QThread的线程类,该类将作为线程池中的线程。

class WorkerThread : public QThread {
public:void run() {while (true) {// 等待任务的到来QMutexLocker locker(&mutex);condition.wait(&mutex);// 执行任务的逻辑if (!tasks.isEmpty()) {QRunnable* task = tasks.dequeue();locker.unlock();task->run();delete task;}}}void addTask(QRunnable* task) {QMutexLocker locker(&mutex);tasks.enqueue(task);condition.wakeOne();}private:QMutex mutex;QWaitCondition condition;QQueue<QRunnable*> tasks;
};

        2、创建一个包含线程池的容器和一些管理方法的自定义的线程池类,用于管理线程池中的线程和任务。

class MyThreadPool {
public:MyThreadPool(int threadCount) {for (int i = 0; i < threadCount; ++i) {WorkerThread* thread = new WorkerThread();thread->start();threads.append(thread);}}~MyThreadPool() {for (WorkerThread* thread : threads) {thread->quit();thread->wait();delete thread;}}void addTask(QRunnable* task) {int index = nextThreadIndex.fetchAndAddRelaxed(1) % threads.size();threads[index]->addTask(task);}private:QVector<WorkerThread*> threads;QAtomicInt nextThreadIndex = 0;
};

        3、在需要使用线程池的地方,创建线程池对象,并将任务提交给线程池执行。

MyThreadPool threadPool(5);
threadPool.addTask(new MyTask());
    自定义线程池类可以根据实际需求进行扩展,例如添加线程的动态增减、任务优先级的管理等功能。需要注意的是,在自定义线程池中,需要手动管理线程的创建、销毁和任务的调度,开发人员需要自行处理线程安全和任务队列的管理,确保线程池的正确运行。

    自定义线程池的好处是可以更灵活地控制线程池的行为,并根据实际需求进行定制化的扩展。但同时也需要开发人员自行处理线程池的细节,包括线程的创建、销毁和任务的调度,相对来说会更复杂一些。因此,在选择实现方式时需要根据实际需求和复杂度进行权衡。


6 小结

整体而言,需要根据实际的具体需求和复杂度,来选择适合的方式来实现线程池功能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/615773.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

性能测试分析案例-定位DNS解析很慢

环境准备 预先安装 docker 等工具&#xff0c;如 apt install docker.io。 操作和解析 执行下面的命令&#xff0c;拉取案例中使用的 Docker 镜像&#xff1a; docker pull feisky/dnsutils运行下面的命令&#xff0c;查看主机当前配置的 DNS 服务器&#xff1a; cat /etc…

你知道谁才是 “最懂程序员” 的搜索引擎?

大家好&#xff0c;我是奇兵&#xff0c;作为一名程序员&#xff0c;我们开发的过程中几乎每天都和搜索引擎打交道&#xff0c;利用它来搜文档、解决 Bug 等等。 而随着 AI 的发展&#xff0c;搜索引擎也变得越来越智能&#xff0c;市面上也涌现除了越来越多的 AI 搜索引擎。 …

【qt】sdk写pro写法,cv,onnx,cudnn

我的sdk在OpenCV003项目里&#xff1a; pro中添加 CONFIG(release, debug|release) {LIBS -L$$PWD/sdk/onnxruntime-x64-gpu/lib/ -lonnxruntimeLIBS -L$$PWD/sdk/onnxruntime-x64-gpu/lib/ -lonnxruntime_providers_cudaLIBS -L$$PWD/sdk/onnxruntime-x64-gpu/lib/ -lon…

GBASE南大通用GBaseCommandBuilder 类

自动生成单表命令&#xff0c;当使用 GBASE南大通用DataSet 对象的方法将变更的内容写回到对应数据库时&#xff0c;需使用GBASE南大通用 GBaseCommandBuilder 进行协调关联。无法继承此类。 对于该类所有成员的列表&#xff0c;参考 GBaseCommandBuilder 成员。 一、继承层次…

深入探索JavaScript中实用而高级的Rest参数和Spread语法

&#x1f9d1;‍&#x1f393; 个人主页&#xff1a;《爱蹦跶的大A阿》 &#x1f525;当前正在更新专栏&#xff1a;《VUE》 、《JavaScript保姆级教程》、《krpano》、《krpano中文文档》 ​ ​ ✨ 前言 函数是JavaScript这个语言的核心,而如何处理函数的参数是函数编程中非…

深度学习工具-Amazon SageMaker使用

Amazon SageMaker 深度学习程序可能需要很多计算资源&#xff0c;这很容易超出你的本地计算机所能提供的范围。云计算服务允许你使用功能更强大的计算机更轻松地运行本书的GPU密集型代码。 注册 首先&#xff0c;我们需要在注册一个帐户https://aws.amazon.com/。 为了增加安…

io.lettuce.core.RedisCommandExecutionException: NOAUTH Authentication required.

报错信息&#xff1a; 浏览器中的报错信息 IDEA中的报错信息 报错原因&#xff1a; SpringBoot整合Redis使用的默认配置&#xff0c;但是我们设置了Redis的密码&#xff0c;而默认配置中密码是为空的&#xff0c;导致不能够连接 浏览器中的报错信息 There was an unexpected …

ChatGLM2-6B 大语言模型本地搭建

ChatGLM模型介绍&#xff1a; ChatGLM2-6B 是清华 NLP 团队于不久前发布的中英双语对话模型&#xff0c;它具备了强大的问答和对话功能。拥有最大32K上下文&#xff0c;并且在授权后可免费商用&#xff01; ChatGLM2-6B的6B代表了训练参数量为60亿&#xff0c;同时运用了模型…

[解决思路]关于h264裸流合成mp4时时间戳添加问题

问题场景&#xff1a; 使用GPU编码(Opencv)生成的h264视频片段中不包含时间戳信息&#xff0c;且含有B帧&#xff0c;直接合成mp4后会导致播放出现问题(瞬间播放完成)。因此&#xff0c;在合成时需要手动添加时间戳。 心路历程&#xff1a; 发现生成的视频会瞬间播放完成后&am…

Mac/Linux虚拟机CrossOver2024新版下载使用教程

CrossOver不像Parallels或VMware的模拟器&#xff0c;而是实实在在Mac OS X系统上运行的一个软件&#xff0c;该软件可以让用户在mac是上直接运行windows软件&#xff0c;本文为大家带来的是CrossOver Mac版安装教程&#xff01; CrossOver Mac-安装包下载如下&#xff1a;http…

zookerper入门

zookerper介绍 ZooKeeper 是一个开源的分布式协调框架,主要用来解决分布式集群中应用系统的一致性问题. ZooKeeper本质上是一个分布式的小文件存储系统&#xff08;Zookeeper文件系统监听机制&#xff09;.提供基于类似于文件系统的目录树方式的数据存储&#xff0c;并且可以…

typora导出html添加目录

typora导出html添加目录 使用方法 首先要从typora导出html文件&#xff0c;之后用记事本编辑器html文件 找到文档最后面&#xff0c;如图&#xff1a; 用文字编辑类工具打开sideBar.txt&#xff0c;复制其中所有内容【内容在下面】 在如上图的位置插入所复制的内容 打开修改…

漏油控制器有用吗?漏油监测器多少钱一个?

漏油控制器也可以被称作漏油监测器、漏油传感器&#xff0c;是漏油检测系统里的一部分&#xff0c;一般是和漏油检测绳组合在一起使用&#xff0c;用来检测油罐、输油管道、油类化工厂等场合是否有油料泄露。很多人刚开始可能会觉得难以置信&#xff0c;这么一个小东西就可以检…

SPDK中常用的性能测试工具

本文主要介绍磁盘性能评估的方法&#xff0c;针对用户态驱动Kernel与SPDK中各种IO测试工具的使用方法做出总结。其中fio是一个常用的IO测试工具&#xff0c;可以运行在Linux、Windows等多种系统之上&#xff0c;可以用来测试本地磁盘、网络存储等的性能。为了和SPDK的fio工具相…

两周掌握Vue3(四):计算属性、监听属性、事件处理

文章目录 一、计算属性1.什么是计算属性2.代码示例 二、监听属性三、事件处理 代码仓库&#xff1a;跳转 当前分支&#xff1a;04 一、计算属性 1.什么是计算属性 Vue 中的计算属性具有以下作用&#xff1a; 数据处理&#xff1a;计算属性可以用于对数据进行处理和计算&…

医院患者满意度抽样方法

医院患者满意度调查的抽样方法是选择一部分患者&#xff0c;代表整体患者群体&#xff0c;以便获取可靠的数据&#xff0c;同时降低成本和时间开销。以下是一些医院患者满意度调查中常用的抽样方法&#xff1a; 简单随机抽样&#xff1a;这是一种最基本的抽样方法&#xff0c;…

格雷希尔G65系列快速接头满足汽车减震器的气压、油压测试要求

当汽车经过不平路面时&#xff0c;汽车减震器可以抑制弹簧吸震后因反弹带来的震荡和来自路面的冲击&#xff0c;为乘客带来平稳舒适的行车体验。减震器在出厂之前&#xff0c;需要模拟汽车的真实行驶环境&#xff0c;在模拟当中需要对它们进行气压和油压的轮番测试。 客户的测试…

ssm基于java web的防疫工作志愿者服务平台的设计与实现论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本防疫工作志愿者服务平台就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数…

PHP短链接url还原成长链接

在开发过程中&#xff0c;碰到了需要校验用户回填的短链接是不是系统所需要的&#xff0c;于是就需要还原找出短链接所对应的长链接。 长链接转短链接 在百度上搜索程序员&#xff0c;跳转页面后的url就是一个长链接。当然你可以从任何地方复制一个长链接过来。 长链接 http…

代码随想录 字符串

344.反转字符串 344. 反转字符串 简单 提示 编写一个函数&#xff0c;其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。 不要给另外的数组分配额外的空间&#xff0c;你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。 示例 1&#xff1a…