浅谈QT的几种线程的使用和区别。

简介:

线程是操作系统中的基本执行单元,是一个独立的执行路径。每个线程都有自己的栈空间,用于存储本地变量和函数调用的上下文。多个线程可以在同一进程中并发执行,从而实现并发处理,提高程序的性能和响应能力。
与进程不同的是,线程是轻量级的,它们共享同一进程的地址空间,这意味着它们可以访问相同的内存和文件资源,从而更容易地共享数据和通信

线程类型:

1、QThread。
2、QObject+moveToThread实现。
3、QThreadPool+QRunnable实现。
4、QFuture+QtConcurrent实现。
5、std::thread实现,不是QT自身的,但是在Qt中使用比较方便也介绍下。

QThread:

介绍:优点是简单易用,能轻松地创建和管理线程。它提供了一些方法来控制线程的生命周期,包括start()和quit()方法来启动和停止线程,以及wait()方法来等待线程完成。
QThread还提供了一些信号来管理线程。例如,finished()信号在线程完成执行后发出,error()信号在线程发生错误时发出。它的线程入口是从run函数开始。
但是它也存在缺点,它只有run函数内部才是在线程范围内,其它函数都是在主线程中。
适用场景:生命周期长但是交互少的场景。
代码:
.h

#include <QThread>
class MThread : public QThread
{Q_OBJECT
public:MThread();void run();
public slots:void test(int val);
};

.cpp

#include "mthread.h"
#include <QDebug>MThread::MThread()
{qDebug()<<"main thread"<<QThread::currentThreadId();
}void MThread::test(int val)
{qDebug()<<"test val"<<QThread::currentThreadId()<<val;
}void MThread::run()
{qDebug()<<"thread 1"<<QThread::currentThreadId();
}

调用

    MThread *thread = new MThread();connect(this,&Widget::sigSendVal,thread,&MThread::test);thread->start();this->sigSendVal(66);thread->wait();thread->exit();

结果:
在这里插入图片描述

QObject+moveToThread实现:

介绍:优点是交互灵活,且跟主线程之间的所有信号槽都是在线程中执行,QThread拥有的线程控制它都具有,如start,quit,wait等等。
缺点:代码逻辑较复杂,使用灵活性没有那么高,由于创建的类较多,内存占用较高,性能相对较低。
适用场景:生命周期长,交互频繁且需要交互逻辑也在线程中的场景。
代码:
.h

#include <QObject>
class MThreadObject : public QObject
{Q_OBJECT
public:MThreadObject();
public slots:void startThread();void slotTest(int val);
};};

.cpp

#include "mthreadobject.h"
#include <QThread>
#include <QDebug>MThreadObject::MThreadObject()
{qDebug()<<"main thread"<<QThread::currentThreadId();
}void MThreadObject::startThread()
{qDebug()<<"thread 2"<<QThread::currentThreadId();
}void MThreadObject::slotTest(int val)
{qDebug()<<"test val"<<QThread::currentThreadId()<<val;
}

调用

    MThreadObject* object = new MThreadObject();QThread* thread2 = new QThread;object->moveToThread(thread2);connect(thread2,&QThread::started,object,&MThreadObject::startThread);connect(this,&Widget::sigSendVal,object,&MThreadObject::slotTest);thread2->start();emit sigSendVal(66); //this->sigSendVal(66) 两种方法都可以

结果
在这里插入图片描述

QThreadPool+QRunnable实现:

介绍:由于线程池原理就是将一堆任务分到设置的几个线程中,按照优先级先后执行,所有在存在大批量任务的时候,可以有效的管理线程的开销。QThreadPool c++实现
缺点:使用起来不是很灵活,由于存在任务排队和优先级设置,所有管理较复杂。
适用场景:需要创建大量生命周期短小,且逻辑重复简单的任务。

int activeThreadCount() const //当前的活动线程数量
void clear()//清除所有当前排队但未开始运行的任务
int expiryTimeout() const//线程长时间未使用将会自动退出节约资源,此函数返回等待时间
int maxThreadCount() const//线程池可维护的最大线程数量
void releaseThread()//释放被保留的线程
void reserveThread()//保留线程,此线程将不会占用最大线程数量,从而可能会引起当前活动线程数量大于最大线程数量的情况
void setExpiryTimeout(int expiryTimeout)//设置线程回收的等待时间
void setMaxThreadCount(int maxThreadCount)//设置最大线程数量
void setStackSize(uint stackSize)//此属性包含线程池工作线程的堆栈大小。
uint stackSize() const//堆大小
void start(QRunnable *runnable, int priority = 0)//加入一个运算到队列,注意start不一定立刻启动,只是插入到队列,排到了才会开始运行。需要传入QRunnable ,后续介绍
bool tryStart(QRunnable *runnable)//尝试启动一个
bool tryTake(QRunnable *runnable)//删除队列中的一个QRunnable,若当前QRunnable 未启动则返回成功,正在运行则返回失败
bool waitForDone(int msecs = -1)//等待所有线程运行结束并退出,参数为等待时间-1表示一直等待到最后一个线程退出
void setAutoDelete(bool flag = true)//QRunnable的设置项,用来标识是否在运行结束后自动由线程池释放空间

代码
.h

#include <QObject>
#include <QRunnable>
class MRunnable : public QObject,public QRunnable
{Q_OBJECT
public:MRunnable(int num);void run();void setval(int index);int _index = 0;int _num = 0;
};

.cpp

#include "mrunnable.h"
#include <QDebug>
#include <QThread>MRunnable::MRunnable(int num)
{qDebug()<<"main thread"<<QThread::currentThreadId();
}void MRunnable::setval(int index)
{qDebug()<<"---------setval"<<index<<QThread::currentThreadId();_index = index;
}void MRunnable::run()
{qDebug()<<_index<<_num<<"thread 3"<<QThread::currentThreadId();QThread::msleep(200);
}

调用

    QThreadPool pool;pool.setMaxThreadCount(3);QList<MRunnable*> runs;for (int i = 0; i < 5; ++i) {MRunnable *run = new MRunnable(44);run->setval(i);pool.start(run);}for (int i = 0; i < runs.size(); ++i) {delete runs[i];}runs.clear();

结果:
在这里插入图片描述

QFuture+QtConcurrent实现:

介绍:QFuture + Qt Concurrent是Qt提供的一个并发编程框架,用于简化多线程和并行计算的开发。它提供了一组易于使用的函数和类,可以方便地在多线程环境下处理并发任务。优点简单易用、自动将大的问题拆分成更小的任务,并分配给不同的线程并行执行、异步计算,不会阻塞主线程。(详细介绍1、详细介绍2)
缺点:交互麻烦。
使用场景:需要临时使用一下线程的场景。
代码
.pro
Qt += concurrent
.h

#include <QWidget>
#include <QDebug>
#include <QFuture>
#include <QtConcurrent>
namespace Ui {
class Widget;
}class Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent = nullptr);~Widget();public slots:void slotFinish();
private:Ui::Widget *ui;QFuture<int> m_future;QFutureWatcher<int> m_watcher;
};

.cpp

#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);auto func([&](int val){val = 2*val;qDebug()<<"thread 4"<<val<<QThread::currentThreadId();return val;});//异步调用QObject::connect(&m_watcher, &QFutureWatcher<void>::finished, this, &Widget::slotFinish);int val = 123;m_future = QtConcurrent::run(func,val);m_watcher.setFuture(m_future);//    future.waitForFinished();//同步调用qDebug()<<"main thread"<<QThread::currentThreadId()<<m_future.result();
}Widget::~Widget()
{delete ui;
}void Widget::slotFinish()
{int res = m_future.result();qDebug()<<"watcher finish"<<res<<QThread::currentThreadId();
}

结果:
在这里插入图片描述

std::thread实现:

介绍:直接调用,优点使用方便灵活。缺点:无法完成复杂的交互。
适用场景:适用需要临时创建线程的场景下。
代码

#include <thread>
void test()
{std::thread thread5([&](){qDebug()<<"thread 5"<<QThread::currentThreadId();});thread5.detach();qDebug()<<"main thread"<<QThread::currentThreadId();```
}

结果
在这里插入图片描述

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

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

相关文章

【Leetcode】1696. 跳跃游戏 VI

文章目录 题目思路代码结果 题目 题目链接 给你一个下标从 0 开始的整数数组 nums 和一个整数 k 。 一开始你在下标 0 处。每一步&#xff0c;你最多可以往前跳 k 步&#xff0c;但你不能跳出数组的边界。也就是说&#xff0c;你可以从下标 i 跳到 [i 1&#xff0c; min(n -…

【Unity3D小技巧】Unity3D中UI控制解决方案

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客 大家好&#xff0c;我是佛系工程师☆恬静的小魔龙☆&#xff0c;不定时更新Unity开发技巧&#xff0c;觉得有用记得一键三连哦。 一、前言 在开发中总是会控制UI界面&#xff0c;如何优雅的控制UI界面是…

3.0 Zookeeper linux 服务端集群搭建步骤

本章节将示范三台 zookeeper 服务端集群搭建步骤。 所需准备工作&#xff0c;创建三台虚拟机环境并安装好 java 开发工具包 JDK&#xff0c;可以使用 VM 或者 vagrantvirtualbox 搭建 centos/ubuntu 环境&#xff0c;本案例基于宿主机 windows10 系统同时使用 vagrantvirtualb…

centos 7.6 安装 openldap 2.5.17

centos 7.6 安装ldap 1、下载ldap2、安装ldap2.1、官方参考文档2.2、安装前准备2.2.1、安装gcc2.2.2、安装Cyrus SASL 2.1.272.2.3、安装OpenSSL 1.1.12.2.3.1、下载openssl 3.02.2.3.2、安装依赖包2.2.3.3、编译安装openssl 3.0 2.2.3、安装libevent 2.1.82.2.4、安装libargon…

小程序支付类型接入京东支付

一、情景描述 当前项目想在微信小程序付款时添加上京东支付支付类型&#xff0c;效果如下 普通的付款方式可以直接付款就能完成支付&#xff0c;但京东支付无法在小程序上直接付款&#xff0c;他需要复制生成的链接&#xff0c;然后打开京东app然后在京东平台上付款。 所以&…

网络安全大赛

网络安全大赛 网络安全大赛的类型有很多&#xff0c;比赛类型也参差不齐&#xff0c;这里以国内的CTF网络安全大赛里面著名的的XCTF和强国杯来介绍&#xff0c;国外的话用DenCon CTF和Pwn2Own来举例 CTF CTF起源于1996年DEFCON全球黑客大会&#xff0c;以代替之前黑客们通过互相…

【开源】JAVA+Vue+SpringBoot实现二手车交易系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 二手车档案管理模块2.3 车辆预约管理模块2.4 车辆预定管理模块2.5 车辆留言板管理模块2.6 车辆资讯管理模块 三、系统设计3.1 E-R图设计3.2 可行性分析3.2.1 技术可行性分析3.2.2 操作可行性3.2.3 经济…

第7节、双电机直线运动【51单片机+L298N步进电机系列教程】

↑↑↑点击上方【目录】&#xff0c;查看本系列全部文章 摘要&#xff1a;前面章节主要介绍单个电机控制&#xff0c;本节内容介绍两个电机完成Bresenham直线运动 一、Bresenham直线算法介绍 Bresenham直线算法由Jack Elton Bresenham于1962年在IBM开发&#xff0c;最初用于计…

python创建pdf文件

目录 一&#xff1a;使用reportlab库 二&#xff1a;使用使pdf库 在Python中生成PDF文件可以使用多种库&#xff0c;其中最常用的是reportlab和fpdf。以下是使用这两个库生成PDF文件的示例代码&#xff1a; 一&#xff1a;使用reportlab库 1&#xff1a;写入文字信息 from r…

使用Pycharm在本地调用chatgpt的接口

目录 1.安装环境 2.建立多轮对话的完整代码&#xff08;根据自己使用的不同代理需要修改端口&#xff08;port&#xff09;&#xff09; 3.修改代码在自己的Pycharm上访问chagpt的api并实现多轮对话&#xff0c;如果不修改是无法成功运行的。需要确定秘钥和端口以保证正常访…

Kafka 使用手册

kafka3.0 文章目录 kafka3.01. 什么是kafka&#xff1f;2. kafka基础架构3. kafka集群搭建4. kafka命令行操作主题命令行【topic】生产者命令行【producer】消费者命令行【consumer】 5. kafka生产者生产者消息发送流程Producer 发送原理普通的异步发送带回调函数的异步发送同步…

【VUE】UniAPP之uview组件库,自定义tag封装,支持添加u-icon图标

组件代码 <template><view class"tag" :class"[props.mode, props.shape]"><slot name"left"><!-- icon图标 没有传入图标时不显示 --><u-icon v-if"props.icon ! " :name"props.icon" :color&…

基于单片机的智能燃气灶控制系统设计

摘要&#xff1a;针对传统燃气灶存在不能防干烧、不能进行温度检测、不能进行火力自动调节等问题&#xff0c;设计了一种基于单片机控制的智能燃气灶&#xff0c;它通过单片机进行控制&#xff0c;由开关模块、测温模块、语音播报模块、火力控制模块和防空烧模块五个模块组成&a…

目标检测:3采用YOLOv8 API训练自己的模型

​ 目录 ​1.YOLOv8 的新特性 2.如何使用 YOLOv8? 3使用YOLOv8训练模型 4.验证训练集 5.测试训练集 6.测验其他图片 7 其他问题 参考: 1.YOLOv8 的新特性 Ultralytics 为 YOLO 模型发布了一个全新的存储库。它被构建为 用于训练对象检测、实例分割和图像分类模型的统…

JVM工作原理与实战(三十六):GraalVM虚拟机

专栏导航 JVM工作原理与实战 RabbitMQ入门指南 从零开始了解大数据 目录 专栏导航 前言 一、GraalVM介绍 二、GraalVM的两种运行模式 三、GraalVM应用场景 1.GraalVM存在的问题 2.GraalVM企业级应用-Serverless架构 3.Serverless架构-函数计算 4.Serverless架构-Serve…

正点原子-STM32定时器学习笔记(1)未完待续

1. 通用定时器简介&#xff08;F1为例&#xff09; F1系列通用定时器有4个&#xff0c;TIM2/TIM3/TIM4/TIM5 主要特性&#xff1a; 16位递增、递减、中心对齐计数器&#xff08;计数值&#xff1a;0~65535&#xff09;&#xff1b; 16位预分频器&#xff08;分频系数&#xff…

视频业务像素、带宽、存储空间计算

一、像素和分辨率 分辨率的单位通常是像素&#xff08;或点&#xff09;&#xff0c;用水平像素数乘以垂直像素数来表示。例如&#xff0c;一个分辨率为1920 x 1080的屏幕有1920个水平像素和1080个垂直像素。 总像素分辨率公式运算 例如 1920 x 10802073600总约200万 500W≈…

get通过发送Body传参-工具类

1、调用方式 String url "http://ip/xxx/zh/xxxxx/xxxx/userCode"; //进行url中的对应的参数 url2 url2.replace("ip",bancirili); url2 url2.replace("zh",zh); url2 url2.replace("userCode",userCode);String dateTime xxxx; //组…

【51单片机】开发板&开发软件(Keil5&STC-ISP)简介&下载安装破译传送门(1)

前言 大家好吖&#xff0c;欢迎来到 YY 滴单片机系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过单片机的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY的…

Android配置GitLab CI/CD持续集成,Shell版本的gitlab-runner,FastLane执行,上传蒲公英

mac环境下&#xff0c; 首选需要安装gitlab-runner和fastlane brew install gitlab-runner brew install fastlane 安装完成&#xff0c;来到我们在gitlab下新建的Android项目&#xff0c;我们开始创建gitlab-runner 1、创建runner 点开runner&#xff0c;点击新建runner …