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

qt线程介绍

目录

介绍

 线程类 QThread

 方式1

方式2

案例

线程资源释放


介绍

qt为多线程提供了完美的支持,实现多线程一般是从从QTHread中继承定义自己的线程类,QT也提供了QMutexLocker,QwaitCondition等类实现线程同步,与Linux系统或C++中的线程库类似。这里简单介绍下多线程的创建。

  • 默认的线程在Qt中称之为窗口线程,也叫主线程,负责窗口事件处理或者窗口控件数据的更新
  • 子线程负责后台的业务逻辑处理,子线程中不能对窗口对象做任何操作,这些事情需要交给窗口线程处理
  • 主线程和子线程之间如果要进行数据的传递,需要使用Qt中的信号槽机制

 线程类 QThread

常用API:

[virtual protected] void QThread::run();

run()是一个虚函数,如果想让创建的子线程执行某个任务,需要写一个子类让其继承QThread,并且在子类中重写父类的run()方法,函数体就是对应的任务处理流程,当前线程对象调用槽函数start()启动子线程,当子线程被启动,这个run()函数也就在线程内部被调用了。

信号与槽函数:

// 线程中执行的任务完成了, 发出该信号
[signal] void QThread::finished();
// 开始工作之前发出这个信号, 一般不使用
[signal] void QThread::started();

[slot] void QThread::quit();


// 启动子线程
[slot] void QThread::start(Priority priority = InheritPriority);
// 线程退出, 可能是会马上终止线程, 一般情况下不使用这个函数
[slot] void QThread::terminate();

 方式1

创建一个线程类的子类,让其继承QT中的线程类 QThread,重写父类的 run() 方法,启动子线程, 调用 start() 方法。

举例:

#ifndef MYTHREAD_H
#define MYTHREAD_H#include <QObject>
#include<QThread>class MyThread : public QThread
{Q_OBJECT
public:explicit MyThread(QObject *parent = nullptr);
protected:void run();
signals:void curNumber(int num);
};#endif // MYTHREAD_H
#include "mythread.h"
#include<QDebug>
MyThread::MyThread(QObject *parent)
{
}void MyThread::run()
{qDebug() << "当前线程对象的地址: " << QThread::currentThread();int num = 0;while(1){emit curNumber(num++);//子线程每秒发出一次信号if(num == 10000000){break;}QThread::usleep(1);}qDebug() << "run() 执行完毕, 子线程退出...";}
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);qDebug() << "主线程对象地址:  " << QThread::currentThread();MyThread* m=new MyThread;connect(m, &MyThread::curNumber, this, [=](int num)//子线程每秒发出一次信号{ui->label->setNum(num);});connect(ui->pushButton, &QPushButton::clicked, this, [=](){// 启动子线程m ->start();});
}MainWindow::~MainWindow()
{delete ui;
}

方式2

  1. 创建一个新的类A,让这个类从QObject派生,这个类中添加一个公共的成员函数来处理对应的任务
  2. 在主线程中创建一个QThread对象
  3. 在主线程中创建工作的类对象A(不能指定父对象)
  4. 将对象A移动到创建的子线程对象中, 需要调用QObject类提供的moveToThread()方法
  5. 启动子线程,调用 start(), 这时候线程启动了, 但是移动到线程中的对象并没有工作
  6. 调用MyWork类对象的工作函数,让这个函数开始执行。

例如:

#ifndef WORK_H
#define WORK_H
#include <QObject>class Work : public QObject
{Q_OBJECT
public:explicit Work(QObject *parent = nullptr);void Working();
signals:void curNumber(int num);};
#endif // WORK_H
#include "work.h"
#include<QDebug>
#include<QThread>
Work::Work(QObject *parent): QObject{parent}
{
}void Work::Working()
{qDebug() << "当前线程对象的地址: " << QThread::currentThread();int num = 0;while(1){emit curNumber(num++);//子线程每秒发出一次信号if(num == 10000000){break;}QThread::usleep(1);}qDebug() << "run() 执行完毕, 子线程退出...";
}
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);qDebug() << "主线程对象地址:  " << QThread::currentThread();QThread* sub = new QThread;//创建线程对象Work* w=new Work;          //创建工作对象,该对象包含业务处理方法,不要指定给创建的对象指定父对象w->moveToThread(sub);    //将工作对象移动到子线程中sub->start();connect(ui->startBtn, &QPushButton::clicked, w,&Work::Working);// 显示数据connect(w, &Work::curNumber, this, [=](int num){ui->label->setNum(num);});
}

案例

在一个子线程程中随机生成1000个数,将这些数据交给另一个子线程去排序,后面将排序的结果返回给主线程,主线程再将数据输出到窗口中。

这里采用方案1进行演示:

生成随机数线程:

class Genera : public QThread //该类来生成随机数
{Q_OBJECT
public:explicit Genera(QObject *parent = nullptr);void getnum(int k);
protected:void run();//重写run方法,生成随机数
private:int num_;  //获取主线程传来的数据,这里为生成随机数的个数signals:void sendnum(QVector<int> v);//当随机数生成完后,发射该信号,将数据传给主线程和排序线程
};Genera::Genera(QObject *parent): QThread{parent}
{
}
void Genera::getnum(int k)
{num_=k;
}
void Genera::run()
{qDebug()<<"当前线程是"<<" "<<QThread::currentThread();QVector<int> v;QElapsedTimer q;q.start();for(int i=0;i<num_;i++){v.push_back(qrand()%10000);}int m=q.elapsed();qDebug()<<"生成随机的时间是"<<" "<<m;emit sendnum(v);}

排序线程:

class BubbleSort : public QThread //该类来生成随机数
{Q_OBJECT
public:explicit BubbleSort(QObject *parent = nullptr);void getnum(QVector<int>);//获取生成随机数线程传来的数据
protected:void run();//进行排序
private:QVector<int> v;signals:void Finish(QVector<int> v);//排序完成后发射该信号,将排序结果给主线程
};BubbleSort::BubbleSort(QObject *parent): QThread{parent}
{ 
}
void BubbleSort::getnum(QVector<int> list)
{v=list;
}
void BubbleSort::run()
{qDebug()<<"当前线程是"<<" "<<QThread::currentThread();QElapsedTimer q;q.start();for(int i=0;i<v.size();i++){for(int j=0;j<v.size()-i-1;j++){if(v[j]>v[j+1]){int tmp=v[j+1];v[j+1]=v[j];v[j]=tmp;}}}int m=q.elapsed();qDebug()<<"排序的时间是"<<" "<<m;emit Finish(v);
}

主线程:

class MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();
signals:void starting(int num);//生成随机数的个数private:Ui::MainWindow *ui;
};
#endif // MAINWINDOW_HMainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);//创建子线程Genera * g=new Genera;//生成随机数BubbleSort* b=new BubbleSort;//排序connect(this,&MainWindow::starting,g,&Genera::getnum);//启动子线程connect(ui->pushButton,&QPushButton::clicked,this,[=](){emit starting(1000);//发射该信号,将生成随机数的个数传给子线程g->start();});connect(g,&Genera::sendnum,b,&BubbleSort::getnum);//排序线程接受生成随机数线程传来的数据//接受子线程传来的排序数connect(g,&Genera::sendnum,this,[=](QVector<int> v){//说明随机生成数已生成好b->start();for(int i=0;i<v.size();i++){ui->listWidget->addItem(QString::number(v.at(i)));}});connect(b,&BubbleSort::Finish,this,[=](QVector<int> v){for(int i=0;i<v.size();i++){ui->listWidget_2->addItem(QString::number(v.at(i)));}});
}MainWindow::~MainWindow()
{delete ui;
}

 结果:

线程资源释放

1.创建线程时,给它指明父对象,让其添加到对象树列表中。

2.手动释放,调用quit,wait,delete:例如,在上面的代码中,new出来的时局部变量:

 connect(this,&MainWindow::destroyed,this,[=](){g->quit();g->wait();g->deleteLater();//类似与c++中delete});

相关文章:

qt线程介绍

目录 介绍 线程类 QThread 方式1 方式2 案例 线程资源释放 介绍 qt为多线程提供了完美的支持&#xff0c;实现多线程一般是从从QTHread中继承定义自己的线程类&#xff0c;QT也提供了QMutexLocker,QwaitCondition等类实现线程同步&#xff0c;与Linux系统或C中的线程库类似…...

记一次用dataframe进行数据清理

总结一下dataframe读取数据库&#xff0c;以及整理数据的过程。分为三个部分&#xff1a;数据读取&#xff0c;数据整理以及数据写入。 1、数据读取 从csv读取读取数据&#xff0c;使用pandas读的read_csv函数&#xff0c;传入两个参数&#xff0c;分别是path文件路径&#x…...

《Jetpack Compose从入门到实战》 第二章 了解常用UI组件

目录 常用的基础组件文字组件图片组件按钮组件选择器组件对话框组件进度条组件 常用的布局组件布局Scaffold脚手架 列表 书附代码 Google的图标库 常用的基础组件 文字组件 Composable fun TestText() {Column(modifier Modifier.verticalScroll(state rememberScrollState…...

Vue3 引入使用 vant组件详解

目录 Vue3 引入使用 vant组件详解1.安装2.引入2.1 全局引入2.2 按需引入2.2.1 vite项目:vite.config.js2.2.2 Webpack项目&#xff1a;webpack.config.js2.2.3 配置在vue.config.js中 3.使用 Vue3 引入使用 vant组件详解 Vant是一个强大的移动端组件库&#xff0c;目前Vant 官…...

NOSQL Redis Ubuntu系列 常用的配置 及密码登录

查看Ubuntu 版本 uname -a 配置redis.conf 查看redis 是否安装成功 ps -ef | grep redis 查看redis 服务状态 service redis status 查看redis 默认安装的路径 whereis redis #sudo vim /etc/redis.conf redis 密码登录...

C语言解析GPS源数据

文章目录 一、GPS数据格式介绍二、GPS字段含义三、C语言解析数据代码3.1 解析每个字段数据3.2 解析定位数据 一、GPS数据格式介绍 GPS&#xff08;全球定位系统&#xff09;数据格式常见的是NMEA 0183格式&#xff0c;NMEA 0183格式是一种用于导航设备间传输数据的标准格式&am…...

【论文阅读】(CVPR2023)用于半监督医学图像分割的双向复制粘贴

目录 前言方法BCPMean-teacher and Traning StrategyPre-Training via Copy-PasteBidirectional Copy-Paste ImagesBidirectional Copy-Paste Supervisory Signals Loss FunctionTesting Phase 结论 先看这个图&#xff0c;感觉比较清晰。它整个的思路就是把有标签的图片和无标…...

[Linux 基础] 一篇带你了解linux权限问题

文章目录 1、Linux下的两种用户2、文件类型和访问权限&#xff08;事物属性&#xff09;2.1 Linux下的文件类型2.2 基本权限2.3 文件权限值的表示方法&#xff08;1&#xff09;字符表示方法&#xff08;2&#xff09;8进制数值表示方法 2.4 文件访问权限的相关设置方法(1) chm…...

FPGA project :HDMI

实验目标&#xff1a;驱动HdMI显示十色等宽彩条。 本实验的重点是&#xff1a; 1掌握TMDS通信协议。 2rgb565转rgb888。 3编写HDMI驱动程序。 4学会看流程图编写代码。 值得注意的事情 1注意数据与解析数据的信号&#xff08;比如传入的数据中0或者1的个数&#xff09;&…...

基于微信小程序的物流快递信息查询平台同城急送小程序(亮点:寄件、发票申请、在线聊天)

文章目录 前言系统主要功能&#xff1a;具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计…...

idea插件推荐

目录 一、插件安装方式 file->settings->plugins->macketplace 各个版本IDE插件界面略有不同&#xff0c;不一一赘述 二、常用插件 1、Background Image Plus 推荐指数&#xff1a;★★★★☆ 这款插件并不能直接提高你的开发效率&#xff0c;但是可以让你面对的ID…...

Arcgis快速计算NDVI

Arcgis快速计算NDVI 一、问题描述 如何使用Arcgis像ENVI一样波段计算NDVI的值&#xff0c;事实上&#xff0c;Arcgis更快速一些。 二、操作步骤 首先准备好影像 打开窗口-影像分析 点击左上角 点击确定 &#xff08;发现自己使用的遥感影像不对劲&#xff0c;是计算好了…...

SpringCloud Alibaba - 基于 FeignClient 整合 Sentinel,实现“线程隔离”和“熔断降级”

目录 一、FeignClient 整合 Sentinel 1.1、整合原因 1.2、实现步骤 1.2.1、修改 OrderService 中的 application.yml 文件 1.2.2、给 FeignClient 编写失败后的降级逻辑 二、线程隔离 2.1、线程隔离的两种方式 2.1.1、线程池隔离 2.1.2、信号量隔离&#xff08;Sentin…...

Acwing 906. 区间分组

Acwing 906. 区间分组 知识点题目描述思路讲解代码展示 知识点 贪心 题目描述 思路讲解 这段代码是用来维护一个最小堆&#xff0c;以确保右边界不相交的区间被正确地保留在堆中。让我详细解释这段代码&#xff1a; heap.empty()&#xff1a;这个条件检查最小堆 heap 是否为…...

阿里云 Oss 权限控制

前言 最近公司的私有 Oss 服务满了&#xff0c;且 Oss 地址需要设置权限&#xff0c;只有当前系统的登录用户才能访问 Oss 下载地址。一开始想着用 Nginx 做个转发来着&#xff0c;Nginx 每当检测当前请求包含特定的 Oss 地址就转发到我们的统一鉴权接口上去&#xff0c;但是紧…...

CSS详细基础(六)边框样式

本期是CSS基础的最后一篇~ 目录 一.border属性 二.边框属性复合写法 三.CSS修改表格标签 四.内边距属性 五.外边距属性 六.其他杂例 1.盒子元素水平居中 2.清除网页内外元素边距 3.外边距的合并与塌陷 4.padding不会撑大盒子的情况 七.综合案例——新浪导航栏仿真 …...

支持向量机SVM:从数学原理到实际应用

目录 一、引言背景SVM算法的重要性 二、SVM基础线性分类器简介什么是支持向量&#xff1f;超平面和决策边界SVM的目标函数 三、数学背景和优化拉格朗日乘子法&#xff08;Lagrange Multipliers&#xff09;KKT条件核技巧&#xff08;Kernel Trick&#xff09;双重问题和主问题&…...

【办公自动化】在Excel中按条件筛选数据并存入新的表(文末送书)

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…...

第三章:最新版零基础学习 PYTHON 教程(第十一节 - Python 运算符—Python 中的any与all)

Any 和 All 是 python 中提供的两个内置函数,用于连续的与/或。Any如果任何一项为 True,则返回 true。如果为空或全部为 false,则返回 False。Any 可以被认为是对所提供的可迭代对象进行 OR 操作的序列。它会短路执行,即一旦知道结果就停止执行。 句法: any(iterable) 函…...

Pytorch单机多卡分布式训练

Pytorch单机多卡分布式训练 数据并行&#xff1a; DP和DDP 这两个都是pytorch下实现多GPU训练的库&#xff0c;DP是pytorch以前实现的库&#xff0c;现在官方更推荐使用DDP&#xff0c;即使是单机训练也比DP快。 DataParallel&#xff08;DP&#xff09; 只支持单进程多线程…...

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序&#xff0c;以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务&#xff0c;提供稳定高效的数据处理与业务逻辑支持&#xff1b;利用 uniapp 实现跨平台前…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

Java线上CPU飙高问题排查全指南

一、引言 在Java应用的线上运行环境中&#xff0c;CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时&#xff0c;通常会导致应用响应缓慢&#xff0c;甚至服务不可用&#xff0c;严重影响用户体验和业务运行。因此&#xff0c;掌握一套科学有效的CPU飙高问题排查方法&…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

Go 并发编程基础:通道(Channel)的使用

在 Go 中&#xff0c;Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式&#xff0c;用于在多个 Goroutine 之间传递数据&#xff0c;从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...