当前位置: 首页 > 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; 只支持单进程多线程…...

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…...

超短脉冲激光自聚焦效应

前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应&#xff0c;这是一种非线性光学现象&#xff0c;主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场&#xff0c;对材料产生非线性响应&#xff0c;可能…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

vue3 定时器-定义全局方法 vue+ts

1.创建ts文件 路径&#xff1a;src/utils/timer.ts 完整代码&#xff1a; import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)

UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中&#xff0c;UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化&#xf…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计&#xff0c;提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合&#xff1a;各模块职责清晰&#xff0c;便于独立开发…...