当前位置: 首页 > news >正文

Qt 多线程 QThread、QThreadPool使用场景

QThread 和 QRunnable 都是 Qt 框架中用于多线程编程的类,它们之间有以下不同点:

  1. 继承关系不同
    QThread 继承自 QObject 类,而 QRunnable 没有父类。

  2. 实现方式不同
    QThread 是一个完整的线程实现,包含了线程的创建、启动、停止、等待等功能。而 QRunnable 是一个任务接口,需要在 QThread 中使用 QThreadPool 或者手动创建线程池来执行任务。

  3. 线程数控制不同
    使用 QThread 时,需要手动创建线程,因此可以直接控制线程数。而使用 QThreadPool 和 QRunnable 时,线程池会自动管理线程,可以通过设置最大线程数来控制并发执行的任务数。

  4. 取消任务的方式不同
    使用 QThread 时,可以通过调用 QThread 的 quit() 方法或者设置一个标志位来取消线程的执行。而在 QRunnable 中,需要使用 QThreadPool 的 cancel() 方法来取消任务的执行。

  总的来说,QThread 适用于需要自行管理线程的情况,比如需要控制线程的生命周期、线程间通信等情况。而 QRunnable 和 QThreadPool 适用于需要管理一组任务的情况,比如大量短时间的计算任务、网络请求等。使用 QThreadPool 和 QRunnable 可以有效地管理线程池和任务队列,避免创建过多的线程导致系统负载过高。

QThread

优点:

  可以使用信号槽进行通信

缺点:

  需要自己管理资源,线程的创建和释放,都需要自己手动管理,并且,频繁的创建和删除会造成比较大的内存开销。

适用场景:

  线程不会被频繁的创建和删除,常驻内存的线程。

QThread 有两种使用方式:

  1. 通过moveToThread()实现 (qt开发者更推荐的方式)
  2. 通过子类继承QThread实现

moveToThread方式

#include <iostream>
#include <QThread>
#include <QDebug>
using namespace std;class worker : public QObject {Q_OBJECT
public slots:void doWork(const QString &parameter) {qDebug() << "work Thread ID:" << QThread::currentThreadId();QString result;emit resultReady(result);}signals:void resultReady(const QString& result);
};class controller : public QObject {Q_OBJECT
public:controller() {worker* w = new worker();w->moveToThread(&_thread);connect(&_thread, &QThread::finished, w, &QObject::deleteLater);connect(this, &controller::begin, w, &worker::doWork);connect(w, &worker::resultReady, this, &controller::handleResults);_thread.start();}~controller() {_thread.quit();_thread.wait();}public slots:void handleResults(const QString& result) { cout << "I'm handleResult" << endl; }signals:void begin(const QString& parameter);private:QThread     _thread;
};
/************测试**************/
#include <QCoreApplication>int main(int argc, char *argv[])
{QCoreApplication app(argc, argv);qDebug() << "main Thread ID: " << QThread::currentThreadId();controller c;emit c.begin("");return app.exec();
}
//输出
main Thread ID:  0x6848
work Thread ID: 0x5724
I'm handleResult

子线程必须在 event loop 里执行,因为子线程是由主线程创建的,如果主线程退出了,子线程会也会立即退出。不管是否执行完。

子类继承QThread方式

#include <iostream>
#include <QThread>
#include <QDebug>
using namespace std;class myThread : public QThread {Q_OBJECT
public:myThread() {connect(this, &myThread::finished, this, &myThread::deleteLater);}void run() override {QString result;qDebug() << "sub Thread ID:" << QThread::currentThreadId();// do somethingemit resultReady(result);}signals:void resultReady(const QString&);
};class myObject : public QObject {Q_OBJECT
public:myObject() {myThread *mt = new myThread();connect(mt, &myThread::resultReady, this, &myObject::handleResult);mt->start();}
public slots:void handleResult(const QString& result) { cout << "I'm handleResult" << endl; }
};
/**********测试******************/
#include <QCoreApplication>int main(int argc, char *argv[])
{QCoreApplication app(argc, argv);qDebug() << "main Thread ID: " << QThread::currentThreadId();myObject mo;return app.exec();
}//输出
main Thread ID:  0x639c
sub Thread ID: 0x75ec
I'm handleResult

注意:
  实例化的子类是在创建线程的旧线程中,不是在新创建的子线程中,该线程的槽函数还是在主线程执行,所以, 不能直接在新建的线程中使用槽。要想在子线程执行槽函数,只能用moveToThread方式
  实例化子类的构造函数和run()函数在不同的线程中运行,因此,假设有成员变量两个函数中都能访问,则需要注意,多线程中资源的访问问题。

QThreadPool与QRunnable

优点:

不用资源管理,QThreadPool 启动线程执行完成后会自动释放

缺点:

可能会形成多线程资源竞争
不能使用信号槽(可以通过继承QObject中使用)

适用场景:

QRunnable适用于线程任务量比较大,需要频繁创建线程的情况。QRunnable能有效减少内存开销。

代码示例

头文件:

#include <QRunnable>
#include <QThread>
#include <QDebug>
#include <QThreadPool>
#include <QSemaphore>using namespace std;class taskQueue {friend class worker;
public:taskQueue(bool useThread);void            calculate();private:void            doTask(int i);private:QThreadPool*    _pool;bool            _useThread;QSemaphore      _sema;
};class worker : public QRunnable {
public:worker(taskQueue* task, int parameter);void            run() override;
private:taskQueue*      _task;int             _parameter;
};

源文件:

taskQueue::taskQueue(bool useThread) : _useThread(useThread) {if (_useThread) {_pool = QThreadPool::globalInstance();_sema.release(QThread::idealThreadCount());}
}void taskQueue::calculate() {for (int i = 0; i < 10; i++) {if (_useThread) {_sema.acquire(); //当线程不够时,等待线程任务完成_pool->start(new worker(this, i));} else {doTask(i);}}_pool->waitForDone();
}void taskQueue::doTask(int i) {// do somethingqDebug() << i << "sub thread" << QThread::currentThreadId();_sema.release();
}worker::worker(taskQueue *task, int parameter): _task(task), _parameter(parameter) {}void worker::run() {_task->doTask(_parameter);
}
/************测试***********/
int main(int argc, char *argv[])
{qDebug() << "main Thread ID: " << QThread::currentThreadId();taskQueue q(1);q.calculate();
}
//输出
main Thread ID:  0x4d3c
2 sub thread 0x5d18
1 sub thread 0x5a68
3 sub thread 0x3d4
4 sub thread 0x4ae0
6 sub thread 0x4f50
8 sub thread 0x480c
0 sub thread 0x7888
7 sub thread 0x2734
5 sub thread 0x7c10
9 sub thread 0x4c98

QtConcurrent

QtConcurrent是一个命名空间,提供了一些高级的 API,使得在编写多线程的时候,无需使用低级线程原语,如读写锁,等待条件或信号。使用QtConcurrent编写的程序会根据可用的处理器内核数自动调整使用的线程数。这意味着今后编写的应用程序将在未来部署在多核系统上时继续扩展。
QtConcurrent::run能够方便快捷的将任务丢到子线程中去执行,无需继承任何类,也不需要重写函数,使用非常简单。

run函数:

template <typename T> 
QFuture<T> QtConcurrent::run(Function function, ...)template <typename T> 
QFuture<T> QtConcurrent::run(QThreadPool *pool, Function function, ...)

不传线程池的相当于:

QtConcurrent::run(QThreadPool::globalInstance(), function, ...);

QtConcurrent 的底层实现是 QThreadPool与QRunnable

相关文章:

Qt 多线程 QThread、QThreadPool使用场景

QThread 和 QRunnable 都是 Qt 框架中用于多线程编程的类&#xff0c;它们之间有以下不同点&#xff1a; 继承关系不同 QThread 继承自 QObject 类&#xff0c;而 QRunnable 没有父类。 实现方式不同 QThread 是一个完整的线程实现&#xff0c;包含了线程的创建、启动、停止、…...

如何一招搞定PCB阻焊过孔问题?

PCB阻焊油墨根据固化方式&#xff0c;阻焊油墨有感光显影型的油墨&#xff0c;有热固化的热固油墨&#xff0c;还有UV光固化的UV油墨。而根据板材分类&#xff0c;又有PCB硬板阻焊油墨&#xff0c;FPC软板阻焊油墨&#xff0c;还有铝基板阻焊油墨&#xff0c;铝基板油墨也可以用…...

【代码随想录】刷题Day2

1.左右指针比大小 977. 有序数组的平方 class Solution { public:vector<int> sortedSquares(vector<int>& nums) {vector<int> ret nums;int left 0;int right nums.size()-1;int end nums.size();while(left<right){if(abs(nums[left])>abs…...

Python机器学习、深度学习技术提升气象、海洋、水文领域实践应用

Python是功能强大、免费、开源&#xff0c;实现面向对象的编程语言&#xff0c;在数据处理、科学计算、数学建模、数据挖掘和数据可视化方面具备优异的性能&#xff0c;这些优势使得Python在气象、海洋、地理、气候、水文和生态等地学领域的科研和工程项目中得到广泛应用。可以…...

计及调度经济性的光热电站储热容量配置方法【IEEE30节点】(Matlab代码实现)

&#x1f4a5; &#x1f4a5; &#x1f49e; &#x1f49e; 欢迎来到本博客 ❤️ ❤️ &#x1f4a5; &#x1f4a5; &#x1f3c6; 博主优势&#xff1a; &#x1f31e; &#x1f31e; &#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 …...

“不要放过这个春天”解锁品牌春日宣传新玩法

在万物复苏的春天&#xff0c;人们换新装、踏青等需求蓄势待发&#xff0c;出现了全民消费热情高涨的趋势&#xff0c;让品牌「贩卖春天」的宣传此起彼伏。 品牌洞察到用户的消费需求&#xff0c;打造具有品牌特色的浪漫宣传&#xff0c;如采用春日限定元素、创新春天宣传场景…...

利用GPT2 预测 福彩3d预测

使用GPT2预测福彩3D项目 个人总结彩票数据是随机的,可以预测到1-2个数字,但是有一两位总是随机的 该项目紧做模型学习用,通过该项目熟练模型训练调用生成过程. 福彩3D数据下载 https://www.17500.cn/getData/3d.TXT data数据格式 处理后数据格式 每行 2023 03 08 9 7 3 训…...

类加载过程

基本说明 反射机制是Java实现动态语言的关键&#xff0c;也就是通过反射实现类动态加载。 静态加载&#xff1a;编译时加载相关的类&#xff0c;如果没有则报错&#xff0c;依赖性太强动态加载&#xff1a;运行时加载需要的类&#xff0c;如果运行时不用该类&#xff0c;即使…...

【C/C++】C++11 无序关联容器的诞生背景

文章目录 背景无序关联容器适用场景有序关联容器适用场景 背景 C11 引入了无序关联容器&#xff08;unordered_map、unordered_set、unordered_multimap 和 unordered_multiset&#xff09;是为了提供一种高效的元素存储和查找方式。相比于有序关联容器&#xff08;map、set、…...

h264编码原理

在介绍编码器原理之前首先了解三个制定编码标准的组织&#xff1a; 1.国际电信联盟(ITU-T)&#xff0c;这是一个音视频领域非常强的组织&#xff0c;规定了很多标准如h261&#xff0c;h262&#xff0c;h263&#xff0c;h263。h263也就是h264的前身。 2.国际标准化组织(ISO)&…...

网络工程师经常搞混的路由策略和策略路由,两者到底有啥区别?

当涉及到网络路由时&#xff0c;两个术语经常被混淆&#xff1a;策略路由和路由策略。虽然这些术语听起来很相似&#xff0c;但它们实际上有着不同的含义和用途。在本文中&#xff0c;我们将详细介绍这两个术语的区别和应用。 一、路由策略 路由策略是指一组规则&#xff0c;用…...

高精度气象模拟软件WRF实践技术

【原文链接】&#xff1a;高精度气象模拟软件WRF(Weather Research Forecasting)实践技术及案例应用https://mp.weixin.qq.com/s?__bizMzU5NTkyMzcxNw&mid2247538149&idx3&sn3890c3b29f34bcb07678a9dd4b9947b2&chksmfe68938fc91f1a99bbced2113b09cad822711e7f…...

总结827

学习目标&#xff1a; 4月&#xff08;复习完高数18讲内容&#xff0c;背诵21篇短文&#xff0c;熟词僻义300词基础词&#xff09; 学习内容&#xff1a; 高等数学&#xff1a;刷1800&#xff0c;做了26道计算题&#xff0c;记录两道错题&#xff0c;搞懂了&#xff0c;但并不…...

还在发愁项目去哪找?软件测试企业级Web自动化测试实战项目

今天给大家分享一个简单易操作的实战项目&#xff08;已开源&#xff09; 项目名称 ET开源商场系统 项目描述 ETshop是一个电子商务B2C电商平台系统&#xff0c;功能强大&#xff0c;安全便捷。适合企业及个人快速构建个性化网上商城。 包含PCIOS客户端Adroid客户端微商城…...

总结下Spring boot异步执行逻辑的几种方式

文章目录 概念实现方式Thread说明 Async注解说明 线程池CompletableFuture&#xff08;Future及FutureTask&#xff09;创建CompletableFuture异步执行 消息队列 概念 异步执行模式&#xff1a;是指语句在异步执行模式下&#xff0c;各语句执行结束的顺序与语句执行开始的顺序…...

【开发日志】2023.04 ZENO----Composite----CompNormalMap

NormalMap-Online (cpetry.github.io)https://cpetry.github.io/NormalMap-Online/ CompNormalMap 将灰度图像转换为法线贴图 将灰度图像转换为法线贴图是一种常见的技术&#xff0c;用于在实时图形渲染中增加表面细节。下面是一个简单的方法来将灰度图像转换为法线贴图&…...

春秋云境:CVE-2022-28525 (文件上传漏洞)

目录 一、题目 1.登录 2.burp抓包改包 3.蚁剑获取flag 一、题目 ED01CMSv20180505存在任意文件上传漏洞 英语不够 翻译来凑&#xff1a; 点击其他页面会Not Found 找不到&#xff1a; 先登录看看吧&#xff1a; 试试万能密码&#xff1a;admin&#xff1a;123 发现错误…...

【软件测试二】开发模型和测试模型,BUG概念篇

目录 1.软件的生命周期 2.瀑布模型 3.螺旋模型 4.增量&#xff0c;迭代 5.敏捷---scrum 1. 敏捷宣言 2.角色 6. 软件测试v模型 7.软件测试w模型 8.软件测试的生命周期 9.如何描述一个BUG 10.如何定义BUG的级别 11.BUG的生命周期 12.产生争执怎么办 1.软件的生命周期…...

短视频app开发:如何实现视频直播功能

短视频源码的实现 在短视频app开发中&#xff0c;实现视频直播功能需要借助短视频源码。短视频源码可以提供一个完整的视频直播功能模块&#xff0c;包括视频采集、编码、推流等。因此&#xff0c;我们可以选择一些开源的短视频源码&#xff0c;例如LFLiveKit、ijkplayer等&am…...

[架构之路-174]-《软考-系统分析师》-5-数据库系统-7-数据仓库技术与数据挖掘技术

5 . 7 数据仓库技术 数据仓库是一个面向主题的、集成的、相对稳定的、反映历史变化的数据集合&#xff0c;用于支持管理决策。近年来&#xff0c;人们对数据仓库技术的关注程度越来越尚&#xff0c;其原因是过去的几十年中&#xff0c;建设了无数的应用系统&#xff0c;积累了…...

label-studio的使用教程(导入本地路径)

文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业

6月9日&#xff0c;国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解&#xff0c;“超级…...

网络编程(UDP编程)

思维导图 UDP基础编程&#xff08;单播&#xff09; 1.流程图 服务器&#xff1a;短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...

AspectJ 在 Android 中的完整使用指南

一、环境配置&#xff08;Gradle 7.0 适配&#xff09; 1. 项目级 build.gradle // 注意&#xff1a;沪江插件已停更&#xff0c;推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

10-Oracle 23 ai Vector Search 概述和参数

一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI&#xff0c;使用客户端或是内部自己搭建集成大模型的终端&#xff0c;加速与大型语言模型&#xff08;LLM&#xff09;的结合&#xff0c;同时使用检索增强生成&#xff08;Retrieval Augmented Generation &#…...

GitFlow 工作模式(详解)

今天再学项目的过程中遇到使用gitflow模式管理代码&#xff0c;因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存&#xff0c;无论是github还是gittee&#xff0c;都是一种基于git去保存代码的形式&#xff0c;这样保存代码…...

git: early EOF

macOS报错&#xff1a; Initialized empty Git repository in /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/.git/ remote: Enumerating objects: 2691797, done. remote: Counting objects: 100% (1760/1760), done. remote: Compressing objects: 100% (636/636…...

车载诊断架构 --- ZEVonUDS(J1979-3)简介第一篇

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…...

高保真组件库:开关

一:制作关状态 拖入一个矩形作为关闭的底色:44 x 22,填充灰色CCCCCC,圆角23,边框宽度0,文本为”关“,右对齐,边距2,2,6,2,文本颜色白色FFFFFF。 拖拽一个椭圆,尺寸18 x 18,边框为0。3. 全选转为动态面板状态1命名为”关“。 二:制作开状态 复制关状态并命名为”开…...

职坐标物联网全栈开发全流程解析

物联网全栈开发涵盖从物理设备到上层应用的完整技术链路&#xff0c;其核心流程可归纳为四大模块&#xff1a;感知层数据采集、网络层协议交互、平台层资源管理及应用层功能实现。每个模块的技术选型与实现方式直接影响系统性能与扩展性&#xff0c;例如传感器选型需平衡精度与…...