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

QT多线程

使用多线程的好处

假如当前窗口要进行一段非常复杂的逻辑处理,在单线程的情况下,是无法操控界面UI的,点击界面UI没有响应。此时就要用到多线程。

注意:

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

线程类QThread

常用公共成员函数:

// QThread 类常用 API
// 构造函数
QThread::QThread(QObject *parent = Q_NULLPTR);
// 判断线程中的任务是不是处理完毕了
bool QThread::isFinished() const;
// 判断子线程是不是在执行任务
bool QThread::isRunning() const;// Qt中的线程可以设置优先级
// 得到当前线程的优先级
Priority QThread::priority() const;
void QThread::setPriority(Priority priority);
优先级:QThread::IdlePriority         --> 最低的优先级QThread::LowestPriorityQThread::LowPriorityQThread::NormalPriorityQThread::HighPriorityQThread::HighestPriorityQThread::TimeCriticalPriority --> 最高的优先级QThread::InheritPriority      --> 子线程和其父线程的优先级相同, 默认是这个
// 退出线程, 停止底层的事件循环
// 退出线程的工作函数
void QThread::exit(int returnCode = 0);
// 调用线程退出函数之后, 线程不会马上退出因为当前任务有可能还没有完成, 调回用这个函数是
// 等待任务完成, 然后退出线程, 一般情况下会在 exit() 后边调用这个函数
bool QThread::wait(unsigned long time = ULONG_MAX);

 信号槽

// 和调用 exit() 效果是一样的
// 调用这个函数之后, 再调用 wait() 函数
[slot] void QThread::quit();
// 启动子线程
[slot] void QThread::start(Priority priority = InheritPriority);
// 线程退出, 可能是会马上终止线程, 一般情况下不使用这个函数
[slot] void QThread::terminate();// 线程中执行的任务完成了, 发出该信号
// 任务函数中的处理逻辑执行完毕了
[signal] void QThread::finished();
// 开始工作之前发出这个信号, 一般不使用
[signal] void QThread::started();

静态函数 

// 返回一个指向管理当前执行线程的QThread的指针
[static] QThread *QThread::currentThread();
// 返回可以在系统上运行的理想线程数 == 和当前电脑的 CPU 核心数相同
[static] int QThread::idealThreadCount();
// 线程休眠函数
[static] void QThread::msleep(unsigned long msecs);	// 单位: 毫秒
[static] void QThread::sleep(unsigned long secs);	// 单位: 秒
[static] void QThread::usleep(unsigned long usecs);	// 单位: 微秒

 任务处理函数

// 子线程要处理什么任务, 需要写到 run() 中
[virtual protected] void QThread::run();

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

使用方法

方式一

1、需要创建一个线程类的子类,让其继承QT中的线程类 QThread,比如:

class MyThread:public QThread
{......
}

2、重写父类的 run() 方法,在该函数内部编写子线程要处理的具体的业务流程

class MyThread:public QThread
{......protected:void run(){........}
}

3、 在主线程中创建子线程对象,new 一个就可以了

MyThread * subThread = new MyThread;

4、 启动子线程, 调用 start() 方法

subThread->start();

不能在类的外部调用run() 方法启动子线程,在外部调用start()相当于让run()开始运行

当子线程别创建出来之后,父子线程之间的通信可以通过信号槽的方式,注意事项:

1、在Qt中在子线程中不要操作程序中的窗口类型对象, 不允许, 如果操作了程序就挂了
2、只有主线程才能操作程序中的窗口对象, 默认的线程就是主线程, 自己创建的就是子线程

弊端:这种在程序中添加子线程的方式是非常简单的,但是也有弊端,假设要在一个子线程中处理多个任务,所有的处理逻辑都需要写到run()函数中,这样该函数中的处理逻辑就会变得非常混乱,不太容易维护。

方式二*

1、创建一个新的类,让这个类从QObject派生

class MyWork:public QObject
{.......
}

2、在这个类中添加一个公共的成员函数,函数体就是我们要子线程中执行的业务逻辑

class MyWork:public QObject
{
public:.......// 函数名自己指定, 叫什么都可以, 参数可以根据实际需求添加void working();
}

3、在主线程中创建一个QThread对象, 这就是子线程的对象

QThread* sub = new QThread;

4、在主线程中创建工作的类对象(千万不要指定给创建的对象指定父对象) 

MyWork* work = new MyWork(this);    // error
MyWork* work = new MyWork;          // ok

5、将MyWork对象移动到创建的子线程对象中, 需要调用QObject类提供的moveToThread()方法

// void QObject::moveToThread(QThread *targetThread);
// 如果给work指定了父对象, 这个函数调用就失败了
// 提示: QObject::moveToThread: Cannot move objects with a parent
work->moveToThread(sub);	// 移动到子线程中工作

6、启动子线程,调用 start(), 这时候线程启动了, 但是移动到线程中的对象并没有工作

7、调用MyWork类对象的工作函数,让这个函数开始执行,这时候是在移动到的那个子线程中运行的

优势:使用这种多线程方式,假设有多个不相关的业务流程需要被处理,那么就可以创建多个类似于MyWork的类,将业务流程放多类的公共成员函数中,然后将这个业务类的实例对象移动到对应的子线程中moveToThread()就可以了,这样可以让编写的程序更加灵活,可读性更强,更易于维护。

示例代码

采用方式二

mywork.h

#ifndef MYWORK_H
#define MYWORK_H#include <QObject>class Generate : public QObject
{Q_OBJECT
public:explicit Generate(QObject *parent = nullptr);void doWork(int num);signals:void sendArray(QVector<int> arrayNum);};//冒泡
class BubbleSort : public QObject
{Q_OBJECT
public:BubbleSort(QObject *parent=nullptr);void doWork(QVector<int> arrayNum);
signals:void finished(QVector<int> arrayNum);
};//快排
class QuickSort : public QObject
{Q_OBJECT
public:QuickSort(QObject *parent=nullptr);void doWork(QVector<int> arrayNum);
signals:void finished(QVector<int> arrayNum);
private:void Quick(QVector<int> &arrayNum,int start,int len);
};#endif // MYWORK_H

widget.h

#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();signals:void starting(int num);private:Ui::Widget *ui;
};#endif // WIDGET_H

main.cpp

#include "widget.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}

 mywork.cpp

#include "mywork.h"
#include<QDebug>
#include <QThread>
#include <QElapsedTimer>
Generate::Generate(QObject *parent): QObject(parent)
{}//生成随机数
void Generate::doWork(int num)
{qDebug()<<"生成随机数的线程地址:"<<QThread::currentThread();QElapsedTimer time;time.start();QVector<int> arrayNum;for(int i=0;i<num;i++){arrayNum.push_back(rand()%100000);//qDebug()<<QString::number(arrayNum.at(i));}int milsec=time.elapsed();qDebug()<<"生成随机数用时:"<<milsec<<"毫秒";emit sendArray(arrayNum);
}BubbleSort::BubbleSort(QObject *parent) :QObject(parent)
{}//冒泡排序
void BubbleSort::doWork(QVector<int> arrayNum)
{qDebug()<<"冒泡排序的线程地址:"<<QThread::currentThread();QElapsedTimer time;time.start();for(int i=0;i<arrayNum.size()-1;i++){for(int j=0;j<arrayNum.size()-i-1;j++){if(arrayNum.at(j)>arrayNum.at(j+1)){int temp=arrayNum.at(j);arrayNum[j]=arrayNum.at(j+1);arrayNum[j+1]=temp;}}}int milsec=time.elapsed();qDebug()<<"冒泡排序用时:"<<milsec<<"毫秒";emit finished(arrayNum);
}QuickSort::QuickSort(QObject *parent) :QObject(parent)
{}//快排,调用快排函数进行快速排序
void QuickSort::doWork(QVector<int> arrayNum)
{qDebug()<<"快速排序的线程地址:"<<QThread::currentThread();QElapsedTimer time;time.start();Quick(arrayNum,0,arrayNum.size()-1);int milsec=time.elapsed();qDebug()<<"快速排序用时:"<<milsec<<"毫秒";emit finished(arrayNum);
}
//快速排序函数,start是起始坐标,len是终止坐标
void QuickSort::Quick(QVector<int> &arrayNum, int start, int len)
{if(start<len){int x=start;int y=len;int temp=arrayNum.at(start);while(x<y){while(arrayNum.at(y)>temp && x<y){y--;}if(x<y){arrayNum[x++]=arrayNum.at(y);}while(arrayNum.at(x)<temp && x<y){x++;}if(x<y){arrayNum[y--]=arrayNum.at(x);}}arrayNum[x]=temp;Quick(arrayNum,start,x-1);Quick(arrayNum,x+1,len);}}

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QPushButton>
#include <QThread>
#include "mywork.h"
#include <QMetaType>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//创建线程对象QThread *t1=new QThread;QThread *t2=new QThread;QThread *t3=new QThread;//创建任务对象,对象不能传入this指针Generate *gen=new Generate;BubbleSort *bubble=new BubbleSort;QuickSort *quick=new QuickSort;gen->moveToThread(t1);bubble->moveToThread(t2);quick->moveToThread(t3);//关联信号曹,参数是widget传递生成随机数的数量connect(this,&Widget::starting,gen,&Generate::doWork);//按下开始按钮后,发送strating信号,开始t1线程connect(ui->pushButton,&QPushButton::clicked,this,[=](){emit starting(10000);t1->start();});//QVector<int>类型在Qt的信号槽跨线程通信中,要注册qRegisterMetaType<QVector<int>>("QVector<int>");//关联信号槽,传输生成的随机数组到排序算法中connect(gen,&Generate::sendArray,bubble,&BubbleSort::doWork);connect(gen,&Generate::sendArray,quick,&QuickSort::doWork);//关系信号槽,随机数生成完毕后,显示到窗口,同时启动线程t2,t3connect(gen,&Generate::sendArray,this,[=](QVector<int> arrayNum){for(int i=0;i<arrayNum.size();i++){//qDebug()<<QString::number(arrayNum.at(i));ui->listWidget->addItem(QString::number(arrayNum.at(i)));}t2->start();t3->start();});//冒泡排序完成,则发送信号,显示到窗口connect(bubble,&BubbleSort::finished,this,[=](QVector<int> arrayNum){for(int i=0;i<arrayNum.size();i++){ui->listWidget_2->addItem(QString::number(arrayNum.at(i)));}});//快速排序完成,则发送信号,显示到窗口connect(quick,&QuickSort::finished,this,[=](QVector<int> arrayNum){for(int i=0;i<arrayNum.size();i++){ui->listWidget_3->addItem(QString::number(arrayNum.at(i)));}});//窗口关闭,销毁开辟的线程和对象connect(this,&Widget::destroyed,this,[=](){//关闭线程t1->quit();t1->wait();t1->deleteLater();t2->quit();t2->wait();t2->deleteLater();t3->quit();t3->wait();t3->deleteLater();//销毁对象gen->deleteLater();bubble->deleteLater();quick->deleteLater();//测试子线程是否还在跑qDebug()<<t1->isRunning();qDebug()<<t2->isRunning();qDebug()<<t3->isRunning();});
}Widget::~Widget()
{delete ui;
}

 线程资源释放

方式一

创建线程时,没传入this指针 

 //线程资源要释放,可以在析构函数中释放//但在此,由于new的对象都是局部变量,析构函数无法访问到,所以释放资源时使用信号槽,在窗口销毁的时候释放资源//创建线程对象(管理线程方式,不指定父类对象,关联槽函数,窗口摧毁时关闭线程和销毁对象)QThread *t1=new QThread;QThread *t2=new QThread;QThread *t3=new QThread;

 释放资源

    connect(this,&Widget::destroyed,this,[=](){//关闭线程t1->quit();t1->wait();t1->deleteLater();t2->quit();t2->wait();t2->deleteLater();t3->quit();t3->wait();t3->deleteLater();//销毁对象gen->deleteLater();bubble->deleteLater();quick->deleteLater();//测试子线程是否还在跑qDebug()<<t1->isRunning();qDebug()<<t2->isRunning();qDebug()<<t3->isRunning();});

方式二

创建线程时指定父类对象

   QThread *t1=new QThread(this);
 1.父子对象销毁规则

当父对象被销毁时,Qt会自动递归销毁其所有子对象
此机制仅适用于QObject及其派生类,并且需显式设置父子关系
线程对象t1需满足两个条件才能被自动销毁:
• t1QObject的派生类(如QThread
• t1的父对象被显式设置为this(例如t1 = new QThread(this)

2.线程对象的特殊性

若线程仍在运行(isRunning()==true)时父对象被销毁:
会触发 ‌"QThread: Destroyed while thread is still running"‌ 错误
导致程序强制终止

原因:线程运行时不接受自动销毁指令

3. ‌安全销毁建议
// 正确做法:析构函数中手动管理线程
~MyClass() {if(t1 && t1->isRunning()) {t1->quit();    // 请求终止t1->wait();    // 阻塞等待结束}// 父对象销毁将自动删除t1(因已设置父子关系)
}

关键步骤:
① 调用quit()终止线程任务
② 使用wait()确保线程完全停止
③ 依赖对象树机制自动回收内存

4. ‌未设置父子关系的场景 
t1 = new QThread();  // 未关联this

 this销毁时‌不会‌自动删除t1

必须手动管理内存:delete t1

总结
条件是否自动销毁风险
设置t1 = new QThread(this) + 线程已停止✅ 是
设置父子关系但线程仍在运行❌ 否程序崩溃
未设置父子关系❌ 否内存泄漏

 最佳实践‌:始终在析构函数中显式调用quit()wait(),即使设置了父子关系

相关文章:

QT多线程

使用多线程的好处 假如当前窗口要进行一段非常复杂的逻辑处理&#xff0c;在单线程的情况下&#xff0c;是无法操控界面UI的&#xff0c;点击界面UI没有响应。此时就要用到多线程。 注意&#xff1a; 1、默认的线程在Qt中称之为窗口线程&#xff0c;也叫主线程&#xff0c;负…...

了解公共部门中的数据网格:支柱、架构和示例

作者&#xff1a;来自 Elastic Elastic Platform Team 想想那些像公共健康记录、城市规划模型等项目背后的所有数据。政府机构一直在产生大量数据。当数据分散在云平台、本地系统或像卫星和应急响应中心这样的专业环境中时&#xff0c;情况变得更加复杂。找到信息变得困难&…...

关于一维数组和字符串的详细讲解(从属于GESP三级)

本章内容 一维数组基础 字符串基础 就像打磨一串符号&#xff0c;每个位置都要精准对待&#xff0c;才能串起完整的风景。坚持下去&#xff0c;小细节终将成就大格局。 一、⼀维数组基础 1 &#x1f4da; 定义 典型写法 说明 易错/拓展 int a[5]; 编译期长度常量&#x…...

【驱动设计的硬件基础】PCI和PCI-E

打开电脑主机&#xff0c;你会看到主板上一排长短不一的插糟&#xff1a;矮胖的 PCI 插糟还插着古老的声卡&#xff0c;旁边细长的 PCI-E 插糟则牢牢卡住显卡、高速网卡等核心设备。这些看似普通的插糟&#xff0c;其实是计算机硬件沟通的 "高速公路"&#xff0c;承载…...

【学习记录】Git Base使用-免密连接代码仓库

github&#xff08;JL765&#xff09;和gitee&#xff08;JL765/git-test01&#xff09;都可以用于管理代码 在windows中&#xff0c;可以通过Git Base软件&#xff08;Git - Downloading Package&#xff09;和仓库进行连接 下载略过 github登录 ssh -T gitgithub.com # 成…...

android脱糖

前言 另外一篇相关文章&#xff1a;https://androidblog.blog.csdn.net/article/details/148574130 通过sourceCompatibility 和targetCompatibility可以实现低版本写代码高版本输出&#xff08;详情可查看我的另一篇文件中的&#xff1a;验证各种Java版本 > 一、纯Java项…...

DVWA Brute Force漏洞深度分析与利用指南

DVWA简介 DVWA&#xff08;Damn Vulnerable Web Application&#xff09;是一个基于PHP/MySQL的脆弱性Web应用平台&#xff0c;专为安全专业人员设计&#xff0c;用于测试技能和工具。它包含十大安全模块&#xff0c;其中Brute Force&#xff08;暴力破解&#xff09;是最基础…...

Docker 报错“x509: certificate signed by unknown authority”的排查与解决实录

目录 &#x1f527;Docker 报错“x509: certificate signed by unknown authority”的排查与解决实录 &#x1f4cc; 问题背景 &#x1f9ea; 排查过程 步骤 1&#xff1a;确认加速器地址是否可访问 步骤 2&#xff1a;检查 Docker 是否真的使用了镜像加速器 步骤 3&…...

采用ArcGIS10.8.2 进行插值图绘制

一、最终成果图展示 二、软件下载 链接: 百度网盘 请输入提取码 密码:azay 三、软件安装 1、在安装之前需要关闭电脑的防火墙及杀毒软件 设置-隐私和安全性-Windows安全中心-防火墙和网络保护 2、软件解压 (1)【ArcGIS_Desktop_1082_180......】“以管理员身份运行”…...

国产安路FPGA纯verilog视频图像去雾,基于暗通道先验算法实现,提供5套TD工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐我已有的所有工程源码总目录----方便你快速找到自己喜欢的项目国产安路FPGA相关方案推荐本博主已有的图像处理方案 3、设计思路框架工程设计原理框图输入Sensor之-->GC0308摄像头输入Sensor之-->OV7725摄像头输入Sensor之--…...

利用大型语言模型增强边缘云 AI 系统安全性

大家读完觉得有帮助及的关注和点赞&#xff01;&#xff01;&#xff01; 抽象 随着边缘计算和云系统在 AI 驱动应用中的广泛应用&#xff0c;如何在确保数据隐私的同时保持高效性能已成为一个紧迫的安全问题。本文提出了一种基于联邦学习的数据协作方法&#xff0c;以提高边缘…...

微信小程序中 rpx与px的区别

在微信小程序中的rpx比px方便的多 <!--pages/welcome/welcome.wxml--> <!--rpx替换px--> <image style"width:200rpx;height: 200rpx"src"/images/avatar/3.png"></image> <text>你好&#xff0c;冻梨</text> <but…...

解锁阿里云AnalyticDB:数据仓库的革新利器

AnalyticDB&#xff1a;云数据仓库新势力 在数字化浪潮中&#xff0c;数据已成为企业的核心资产&#xff0c;而云数据仓库作为数据管理与分析的关键基础设施&#xff0c;正扮演着愈发重要的角色。阿里云 AnalyticDB 作为云数据仓库领域的佼佼者&#xff0c;以其卓越的性能、创…...

告别水印烦恼,一键解锁高清无痕图片与视频!

在这个数字化飞速发展的时代&#xff0c;无论是设计小白还是创意达人&#xff0c;都可能遇到这样的困扰&#xff1a;心仪的图片或视频因水印而大打折扣&#xff0c;创意灵感因水印而受限。别急&#xff0c;今天就为大家带来几款神器&#xff0c;让你轻松告别水印烦恼&#xff0…...

前端面试记录

前言&#xff1a;面试题永远是刷不完的&#xff0c;即使刷了一大堆下次面试又忘记了&#xff0c;重要的是组织自己的语言&#xff0c;保持自信&#xff0c;不给自己制造面不过的心理负担&#xff0c;对刷过的题要有个大致印象&#xff0c;好在答题的时候能够多多少少说出点贴近…...

RAG实战基础篇/windows电脑快速部署qwen3:14B

现阶段&#xff0c;在本地部署ollama非常简单&#xff0c;准备好一个有GPU的电脑&#xff0c;十分钟轻松部署qwen3:14b。实现本地的大模型部署。 我这里为了方便起见&#xff0c;直接使用windows电脑下载一个ollama。 访问ollama GIthub地址&#xff1a;ollama开源地址 直接…...

Java SE - 图书管理系统模拟实现

目录 1.设计框架2. 实现用户类3.实现书和书架类4.登录界面的实现5.实现menu方法6.测试菜单选择7.实现一个IFun接口7.1 查找功能的实现7.2 展示功能的实现7.3 增加功能的实现7.4 删除功能的实现7.5 退出功能的实现7.6 借阅功能的实现7.7 归还功能的实现 8.实现IFuntion类型的数组…...

华为HN8145V光猫改华为蓝色公版界面,三网通用,xgpon公版光猫

咸鱼只卖20多元一个&#xff0c;还是xgpon的万兆猫&#xff0c;性价比不错哦 除了没有2.5G网口&#xff0c;其他还行。 改成公版光猫后&#xff0c;运营商是无法纳管光猫&#xff0c;无法后台修改光猫数据及超密。 华为 HN8145V 光猫具有以下特点&#xff1a; 性能方面 高速接…...

【ARM 嵌入式 编译系列 7.5 -- GCC 打印链接脚本各段使用信息】

文章目录 Overview1 在 linker script 中定义符号2 编译并生成 ELF 文件3 使用 nm awk 输出各段地址及大小&#xff08;含单位&#xff09;4 实际输出示例5 进阶建议 Overview 在 GCC 编译生成 elf 后 打印出出数据段的开始地址及结束地址&#xff0c;bss 段的开始地址和结束…...

在大数据求职面试中如何回答分布式协调与数据挖掘问题

在大数据求职面试中如何回答分布式协调与数据挖掘问题 场景&#xff1a;小白的大数据求职面试 小白是一名初出茅庐的程序员&#xff0c;今天他来到一家知名互联网公司的面试现场&#xff0c;面试官是经验丰富的老黑。以下是他们之间的对话&#xff1a; 第一轮提问&#xff1…...

小白成长之路--nginx基础配置(一)

文章目录 一、概述1.1 Nginx 特点1.2 Nginx 作用1.3Nginx工作原理 二、Nginx服务搭建2.1安装2.2 目录结构2.3 配置文件作用2.4 nginx,conf配置文件详解2.5 核心命令2.6 Nginx信号三.Nginx3.1启动 总结 一、概述 Nginx 是开源、高性能、高可靠的 Web服务器 和反向代理服务器&am…...

基于 SpringBoot+JSP 的医疗预约与诊断系统设计与实现

摘要 本研究针对传统医疗预约与诊断流程中存在的效率低下、信息不透明、患者等待时间长等问题&#xff0c;设计并实现了一个基于 SpringBootJSP 的医疗预约与诊断系统。系统采用 B/S 架构&#xff0c;整合了用户管理、科室管理、医生排班、预约挂号、在线问诊、检查检验、诊断…...

C++语言发展历程-2025

C语言发展历程-2025 前言 C是一种高级编程语言&#xff0c;由Bjarne Stroustrup于1979年在贝尔实验室创建&#xff0c;是C语言的扩展和改进版。 C从最初的C with class&#xff0c;经历了C98、C03、C11、C 14、C17、C20、C23多次标准化改造&#xff0c;成为一门多范式、高性…...

Zynq + FreeRTOS + YAFFS2 + SQLite3 集成指南

Zynq FreeRTOS YAFFS2 SQLite3 集成指南 一、系统架构设计 #mermaid-svg-qvuP6slyza89wsiT {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-qvuP6slyza89wsiT .error-icon{fill:#552222;}#mermaid-svg-qvuP6slyz…...

Python基础之函数

代码仓库地址&#xff1a;gitgithub.com:Liucc-123/python_learn.git 函数介绍 函数是组织好的、可重复使用的&#xff0c;用来实现单一、或相关功能的代码段。 函数可以提高应用的模块性和代码的可重复性。python 有许多内置的函数比如 print 打印函数&#xff0c;python 也…...

Python异步爬虫编程技巧:从入门到高级实战指南

Python异步爬虫编程技巧&#xff1a;从入门到高级实战指南 &#x1f680; &#x1f4da; 目录 前言&#xff1a;为什么要学异步爬虫异步编程基础概念异步爬虫核心技术栈入门实战&#xff1a;第一个异步爬虫进阶技巧&#xff1a;并发控制与资源管理高级实战&#xff1a;分布式…...

Redis哨兵模式深度解析与实战部署

Redis哨兵模式深度解析与实战部署 文章目录 Redis哨兵模式深度解析与实战部署一、Redis哨兵模式理论架构详解1.1 哨兵模式的核心架构组成基础架构拓扑图 1.2 哨兵节点的核心功能模块1.2.1 监控模块&#xff08;Monitoring&#xff09;1.2.2 决策模块&#xff08;Decision Makin…...

【软考高级系统架构论文】论边缘计算及其应用

论文真题 边缘计算是在靠近物或数据源头的网络边缘侧,融合网络、计算、存储、应用核心能力的分布式开放平台(架构),就近提供边缘智能服务。边缘计算与云计算各有所长,云计算擅长全局性、非实时、长周期的大数据处理与分析,能够在长周期维护、业务决策支撑等领域发挥优势;…...

触摸屏(典型 I2C + Input 子系统设备)从设备树解析到触摸事件上报

触摸屏&#xff08;典型 I2C Input 子系统设备&#xff09;从设备树解析到触摸事件上报 以下是架构图&#xff0c;对触摸屏&#xff08;典型I2C Input子系统设备&#xff09;从设备树解析到触摸事件上报的全流程详细拆解&#xff0c;包含文字讲解和配套流程图&#xff1a; 注…...

Java中==与equals()方法的深度解析

作为Java后端开发者&#xff0c;我们经常会遇到需要比较两个对象是否相等的情况。在Java中&#xff0c;运算符和equals()方法都可以用于比较&#xff0c;但它们之间存在着本质的区别。 1. 运算符 是一个比较运算符&#xff0c;它的行为取决于比较的类型&#xff1a; 1.1 比较…...

qt常用控件--02

文章目录 qt常用控件--02toolTip属性focusPolicy属性styleSheet属性补充知识点按钮类控件QPushButton 结语 很高兴和大家见面&#xff0c;给生活加点impetus&#xff01;&#xff01;开启今天的编程之路&#xff01;&#xff01; 今天我们进一步c11中常见的新增表达 作者&…...

AI-Sphere-Butler之如何将豆包桌面版对接到AI全能管家~新玩法(一)

环境&#xff1a; AI-Sphere-Butler VBCABLE2.1.58 Win10专业版 豆包桌面版1.47.4 ubuntu22.04 英伟达4070ti 12G python3.10 问题描述&#xff1a; AI-Sphere-Butler之如何将豆包桌面版对接到AI全能管家~新玩法&#xff08;一&#xff09; 聊天视频&#xff1a; AI真…...

为什么android要使用Binder机制

1.linux中大多数标准 IPC 场景&#xff08;如管道、消息队列、ioctl 等&#xff09;的进程间通信机制 ------------------ ------------------ ------------------ | 用户进程 A | | 内核空间 | | 用户进程 B | | (User Spa…...

Apache SeaTunnel Flink引擎执行流程源码分析

目录 1. 任务启动入口 2. 任务执行命令类:FlinkTaskExecuteCommand 3. FlinkExecution的创建与初始化 3.1 核心组件初始化 3.2 关键对象说明 4. 任务执行:FlinkExecution.execute() 5. Source处理流程 5.1 插件初始化 5.2 数据流生成 6. Transform处理流程 6.1 插…...

XML读取和设置例子

在Qt C中&#xff0c;可以使用Qt的 QDomDocument类来读取、更新和保存XML文件。这个类提供了对XML文档的强大操作能力&#xff0c;支持通过DOM&#xff08;文档对象模型&#xff09;对XML进行读取、修改、添加和删除节点等操作。 下面是一个详细的例子&#xff0c;演示如何在Qt…...

数据标注师学习内容

目录 文本标注词性标注实体标注 图像标注语音标注 文本标注 词性标注 第一篇 第二篇 实体标注 点击这里 关系标注 事件标注 意图标注 关键词标注 分类标注 问答标注 对话标注 图像标注 拉框标注 关键点标注 2D标注 3D标注 线标注 目标跟踪标注 OCR标注 图像分类标注 语音…...

如何实现财务自由

如果有人告诉你&#xff0c;普通人也可以在5到10年内&#xff0c;而不是40到50年后实现财务自由、彻底退休&#xff0c;你会不会觉得对方在开玩笑&#xff1f;但这并非天方夜谭&#xff0c;《百万富翁快车道》的作者MJ德马科就是成功案例。他曾和多数人一样做底层工作&#xff…...

一些想法。。。

1.for里面的局部变量这种还是在for里面定义比较好 比如 for(int i 0;i<n;i){ int num; cin>>num; } 实不相瞒&#xff0c;有一次直接cin了i怎么都没看出来哪里错了。。。 2.关于long long 如果发现中间结果大约是10^9&#xff0c;就要考虑int 溢出 即用 long …...

基于分布式部分可观测马尔可夫决策过程与联邦强化学习的低空经济智能协同决策框架

基于分布式部分可观测马尔可夫决策过程与联邦强化学习的低空经济智能协同决策框架 摘要: 低空经济作为新兴战略产业,其核心场景(如无人机物流、城市空中交通、低空监测)普遍面临环境动态性强、个体观测受限、数据隐私敏感及多智能体协同复杂等挑战。本文创新性地提出一种深…...

github常用插件

一&#xff0c;文档辅助阅读系列&#xff1a;自动化wiki处理 1&#xff0c;deepwiki https://deepwiki.com/ 将我们看不懂的官方code文档转换为wiki&#xff0c;更加便于理解。 其实能够翻阅的仓库很有限&#xff0c;比如说&#xff1a; 但是有很多仓库并没有index&#xff…...

python3字典

1 字典简介 字典是一种可变容器模型&#xff0c;且可存储任意类型对象。字典每个基本元素都包括两个部分&#xff1a; 键&#xff08;key&#xff09;和键对应的值&#xff08;value&#xff09; 每个键值 key>value 对用冒号: 分割&#xff0c;每个对之间用逗号(,)分割&am…...

华为云 Flexus+DeepSeek 征文|增值税发票智能提取小工具:基于大模型的自动化信息解析实践

华为云 FlexusDeepSeek 征文&#xff5c;增值税发票智能提取小工具&#xff1a;基于大模型的自动化信息解析实践 前言背景 企业财务处理中&#xff0c;增值税发票信息手动提取存在效率低、易出错等痛点&#xff0c;华为云 Flexus 弹性算力联合 DeepSeek 大模型&#xff0c;通过…...

[特殊字符] OpenCV opencv_world 模块作用及编译实践完整指南

&#x1f4cc; 什么是 opencv_world 模块&#xff1f; opencv_world 是 OpenCV 官方提供的一个 大型集成动态库。它将 OpenCV 所有启用的模块&#xff08;例如 core, imgproc, highgui, videoio, dnn, photo 等&#xff09;打包到一个单一的动态库文件&#xff08;如 Linux 的…...

目标检测之YOLOv5到YOLOv11——从架构设计和损失函数的变化分析

YOLO&#xff08;You Only Look Once&#xff09;系列作为实时目标检测领域的标杆性框架&#xff0c;自2016年YOLOv1问世以来&#xff0c;已历经十余年迭代。本文将聚焦YOLOv5&#xff08;2020年发布&#xff09;到YOLOv11&#xff08;2024年前后&#xff09;的核心技术演进&am…...

Java的SpringAI+Deepseek大模型实战【二】

文章目录 背景交互方式1、等待式问答2、流式问答 设置角色环绕增强1&#xff09;修改controller2&#xff09;修改配置日志级别 处理跨域 背景 上篇【Java的SpringAIDeepseek大模型实战【一】】搭建起浏览器交互的环境&#xff0c;如何进行流式问答&#xff0c;控制台打印日志…...

OpenCV——霍夫变换

霍夫变换 一、霍夫变换原理二、霍夫线检测2.1、标准霍夫变换2.2、概率霍夫变换 三、霍夫圆检测3.1、霍夫圆检测的原理3.2、霍夫梯度法 一、霍夫变换原理 霍夫变换&#xff08;Hough TRansform&#xff09;是从图像中识别几何图形的基本方法&#xff0c;由Paul Hough于1962年提…...

线程池 JMM 内存模型

线程池 & JMM 内存模型 文章目录 线程池 & JMM 内存模型线程池线程池的创建ThreadPoolExecutor 七大参数饱和策略ExecutorService 提交线程任务对象执行的方法&#xff1a;ExecutorService 关闭线程池的方法&#xff1a;线程池最大线程数如何确定&#xff1f; volatile…...

PillarNet: Real-Time and High-PerformancePillar-based 3D Object Detection

​ECCV 2022 paper&#xff1a;[2205.07403] PillarNet: Real-Time and High-Performance Pillar-based 3D Object Detection&#xfeff; code&#xff1a;https://github.com/VISION-SJTU/PillarNet-LTS&#xfeff; 纯点云基于pillar3D检测模型 网络比较 SECOND 基于vo…...

配电抢修场景案例

以配电抢修场景为例来展示关键业务活动。配电抢修愿景分成业务逻辑、业务活动、业务特征、技术支撑、KPI五个层次&#xff0c;分别从策略、执行、评价、资源、协同5个方面描述配电抢修愿景的关键业务活动。...

H5新增属性

✅ 一、表单相关新增属性&#xff08;Form Attributes&#xff09; 这些属性增强了表单功能&#xff0c;提升用户体验和前端验证能力。 1. placeholder 描述&#xff1a;在输入框为空时显示提示文本。示例&#xff1a; <input type"text" placeholder"请输…...