Linux线程控制
POSIX线程库
- 与线程有关的函数构成了一个完整的系列,绝大多数函数的名字都是以“pthread_”打头的
- 要使用这些函数库,要通过引入头文 <pthread.h>
- 链接这些线程函数库时要使用编译器命令的“-lpthread”选项
创建线程
功能:创建⼀个新的线程
原型:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *
(*start_routine)(void*), void *arg);
参数:
thread:返回线程ID
attr:设置线程的属性,attr为NULL表⽰使⽤默认属性
start_routine:是个函数地址,线程启动后要执⾏的函数
arg:传给线程启动函数的参数
返回值:成功返回0;失败返回错误码
错误检查:
- 传统的一些函数是,成功返回0,失败返回-1,并且对全局变量errno赋值以指示错误。
- pthreads函数出错时不会设置全局变量errno(而大部分其他POSIX函数会这样做)。而是将错误代码通过返回值返回
- pthreads同样也提供了线程内的errno变量,以支持其它使用errno的代码。对于pthreads函数的错误,建议通过返回值业判定,因为读取返回值要比读取线程内的errno变量的开销更小
#include<iostream>
#include<string>
#include<pthread.h>
#include<unistd.h>void * routine(void * args)
{std::string name=static_cast<const char*>(args);int cnt=10;while(cnt--){std::cout<<"线程名字:"<<name<<std::endl;sleep(1);}return (void*)10;
}
int main()
{pthread_t tid;
pthread_create(&tid,nullptr,routine,(void*)"thread-1");int cnt=5;
while(cnt--)
{std::cout<<"main线程名字:"<<std::endl;sleep(1);
}
void *ret=nullptr;
pthread_join(tid,&ret);
std::cout<<"新线程结束,退出码:"<<(long long)ret<<std::endl;
}
1.main函数结束,代表主线程结束,一般代表进程结束
2.新线程对应的入口函数运行结束,代表当前线程运行结束
3.给线程传递的参数和返回值,可以是任意类型
有一个任务Task,Result计算任务结果,通过参数交给线程处理,再以退出码返回得到结果
#include<iostream>
#include<string>
#include<pthread.h>
#include<unistd.h>class Task
{public:Task(int a,int b):_a(a),_b(b){}~Task(){}int Exectue(){return _a+_b;}private:int _a;int _b;
};class Result
{public:Result(int result):_result(result){}~Result(){}int GetResult(){return _result;}private:int _result;
};void * routine(void * args)
{Task *t =static_cast<Task*>(args);sleep(1);Result *res=new Result(t->Exectue());sleep(1);return (void *)res;
}
int main()
{pthread_t tid;
Task *t=new Task(10,20);
pthread_create(&tid,nullptr,routine,t);Result *ret=nullptr;
pthread_join(tid,(void**)&ret);
std::cout<<"新线程结束,运行结果:"<<ret->GetResult()<<std::endl;
}
线程ID
pthread_self
#include <pthread.h>
// 获取线程ID
pthread_t pthread_self(void);
打印出来的 tid 是通过 pthread 库中有函数 pthread_self 得到的,它返回一个 pthread_t 类型的
变量,指代的是调用pthread_self 函数的线程的 “ID”。
怎么理解这个“ID”呢?这个“ID”是 pthread 库给每个线程定义的进程内唯⼀标识,是 pthread 库
维持的。
由于每个进程有自己独立的内存空间,故此“ID”的作用域是进程级而非系统级(内核不认识)。
其实 pthread 库也是通过内核提供的系统调用(例如clone)来创建线程的,而内核会为每个线程创建系统全局唯一的“ID”来唯一标识这个线程。
$ ps -aL | head -1 && ps -aL | grep mythread
PID
LWP TTY
TIME CMD
2711838 2711838 pts/235 00:00:00 mythread
2711838 2711839 pts/235 00:00:00 mythread
-L 选项:打印线程信息
LWP 是什么呢?LWP 得到的是真正的线程ID。之前使用 pthread_self 得到的这个数实际上是⼀
个地址,在虚拟地址空间上的⼀个地址,通过这个地址,可以找到关于这个线程的基本信息,包括线程ID,线程栈,寄存器等属性。
在 ps -aL 得到的线程ID,有⼀个线程ID和进程ID相同,这个线程就是主线程,主线程的栈在虚拟
地址空间的栈上,而其他线程的栈在是在共享区(堆栈之间),因为pthread系列函数都是pthread库提供给我们的。而pthread库是在共享区的。所以除了主线程之外的其他线程的栈都在共享区。
长话短说:线程ID不同于进程ID,进程ID是操作系统给进程分配的统一标识方便进程管理,而线程ID是线程内部方便管理线程而统一标识的,操作系统不认线程ID,同一进程的不同线程PID相同,而LWD(TID)不同,对PID操作相当于对所有TID操作,对某个TID操作一般不影响同一个进程下的其他线程
线程终止
不能使用exit()来结束线程,exit是操作系统对进程的结束命令,调用后会杀手全部同一进程下的全部线程,所有得用专门的接口
如果需要只终止某个线程而不终止整个进程,可以有三种方法:
1. 从线程函数return。这种方法对主线程不适用,从main函数return相当于调用exit。
2. 线程可以调用pthread_ exit终止自己。
3. 一个线程可以调用pthread_ cancel终止同一进程中的另一个线程。
pthread_exit
功能:线程终⽌
原型:
void pthread_exit(void *value_ptr);
参数:
value_ptr:value_ptr不要指向⼀个局部变量。
返回值:
⽆返回值,跟进程⼀样,线程结束的时候⽆法返回到它的调⽤者(⾃⾝)
需要注意,pthread_exit或者return返回的指针所指向的内存单元必须是全局的或者是用malloc分配的,不能在线程函数的栈上分配,因为当其它线程得到这个返回指针时线程函数已经退出了,再访问就是野指针。
pthread_cancel函数
功能:取消⼀个执⾏中的线程
原型:
int pthread_cancel(pthread_t thread);
参数:
thread:线程ID
返回值:成功返回0;失败返回错误码
线程等待
为什么需要线程等待?
- 已经退出的线程,其空间没有被释放,仍然在进程的地址空间内。
- 创建新的线程不会复用刚才退出线程的地址空间。
pthread_join
功能:等待线程结束
原型
int pthread_join(pthread_t thread, void **value_ptr);
参数:
thread:线程ID
value_ptr:它指向⼀个指针,后者指向线程的返回值
返回值:成功返回0;失败返回错误码
调用该函数的线程将挂起等待,直到id为thread的线程终止。thread线程以不同的方法终止,通过
pthread_join得到的终止状态是不同的,总结如下:
1. 如果thread线程通过return返回,value_ ptr所指向的单元里存放的是thread线程函数的返回值。
2. 如果thread线程被别的线程调用pthread_ cancel异常终掉,value_ ptr所指向的单元里存放的是常
数PTHREAD_ CANCELED。
3. 如果thread线程是自己调用pthread_exit终止的,value_ptr所指向的单元存放的是传给pthread_exit的参数。
4. 如果对thread线程的终止状态不感兴趣,可以传NULL给value_ ptr参数。
线程分离
pthread_join
默认情况下,新创建的线程是joinable的,线程退出后,需要对其进行pthread_join操作,否则
无法释放资源,从而造成系统泄漏。如果不关心线程的返回值,join是一种负担,这个时候,我们可以告诉系统,当线程退出时,自动释放线程资源。分离的线程在未退出的情况下,依旧在进程的地址空间中,进程的所有资源,被分离的进程依旧可以访问,可以操作。
int pthread_detach(pthread_t thread);
可以是线程组内其他线程对目标线程进行分离,也可以是线程自己分离:
pthread_detach(pthread_self());
joinable和分离是冲突的,一个线程不能既是joinable又是分离的。
#include <iostream>
#include <string>
#include <pthread.h>
#include <unistd.h>
#include <cstdio>
#include <cstring>void *routine(void *args)
{int cnt = 5;while (cnt--){std::cout << "新线程" << std::endl;sleep(1);}return nullptr;
}
int main()
{pthread_t tid;pthread_create(&tid, nullptr, routine, (void *)"pthead-1");// 主分新pthread_cancel(tid);std::cout << "新线程被取消" << std::endl;int cnt = 5;while (cnt--){std::cout << "main线程" << std::endl;sleep(1);}int n = pthread_join(tid, nullptr);if (n != 0){std::cout << "pthread_join error:" << strerror(n) << std::endl;}else{std::cout << "pthread_join success" << strerror(n) << std::endl;}
}
被分离的线程不能被线程等待,会失败
#include <iostream>
#include <string>
#include <pthread.h>
#include <unistd.h>
#include <cstdio>
#include <cstring>void *routine(void *args)
{int cnt = 5;while (cnt--){std::cout << "新线程" << std::endl;sleep(1);}return nullptr;
}
int main()
{pthread_t tid;pthread_create(&tid, nullptr, routine, (void *)"pthead-1");// 主分新pthread_detach(tid);std::cout << "新线程被分离" << std::endl;int cnt = 5;while (cnt--){std::cout << "main线程" << std::endl;sleep(1);}int n = pthread_join(tid, nullptr);if (n != 0){std::cout << "pthread_join error:" << strerror(n) << std::endl;}else{std::cout << "pthread_join success" << strerror(n) << std::endl;}
}
线程ID及进程地址空间布局
Linux本身没有线程,它是用轻量级进程模拟出来的,OS提供的接口,不会直接提供线程接口,在用户层,封装轻量级进程,形成原生线程库:
可执行程序依赖对应的库,两个都是ELF可执行程序,我们可执行程序加载,形成进程,动态链接和动态地址重定向,要将动态库加载到内存还要映射到当前进程的地址空间中
当我们运行可执行文件,首先进程创建一个test——struct的结构体,创建地址空间,链接库,将pthread加载到内存并映射到地址空间,我自己写的代码会用到pthead中的变量方法,采用库的起始地址+偏移量就能访问库的内容,线程的概念是在库里维护的,在库内部,就一定会存在多个被创建好的线程,库也要管理线程,线程也有自己独立的栈
先描述,再组织,我们没创建一个线程,就会在库内创建一个描述线程的结构体,开头就是描述线程的TCB,struct pthread存有各种属性,线程局部存储可以存放各个线程单独的变量,独立访问,再次创建线程,会在上一个线程的实例化后面紧挨着再次创建对应的TCB,而pthread_create()有一个很大的返回值,那不是LWP,而是线程在库当中对应管理块的虚拟地址,线程控制块种有一个void* ret;当这个控制块对应的代码执行完会把返回值写到对应的ret内,线程运行结束资源并没有被释放,所以线程需要pthread_join,线程结束只是函数结束完了,对应的管理块并没有被释放,pthread_join种传入的tid就是上一个执行完的线程的tid,通过该函数再把上一个线程的运行结果带出开,然后释放该控制块的资源,并解决内存泄漏
所以,我在自己的代码里面调用pthread_create,是在动态库内部帮我们创建动态库描述的控制块,管理块的开头叫TCB,里面包含了描述线程的相关信息,而TCB里包含了void *ret字段,而当前线程运行结束的时候,会把自己的退出状态写到自己的控制块ret里,然后主线程又和新线程共享地址空间,主线程也就能通过起始地址+偏移量找到对应线程的控制块,主线程通过pthread_join拿到对应的退出状态拷贝回来,进程结束LWP自动释放,但是库里的东西没被释放,LWP查不到内存泄漏
- pthread_ create函数会产生一个线程ID,存放在第一个参数指向的地址中。该线程ID和前面说的线程ID不是一回事。
- 前面讲的线程ID属于进程调度的范畴。因为线程是轻量级进程,是操作系统调度器的最小单位,所以需要一个数值来唯一表示该线程。
- pthread_ create函数第一个参数指向一个虚拟内存单元,该内存单元的地址即为新创建线程的线程ID,属于NPTL线程库的范畴。线程库的后续操作,就是根据该线程ID来操作线程的。
- 线程库NPTL提供了pthread_ self函数,可以获得线程自身的ID:
pthread_t pthread_self(void);
pthread_t 到底是什么类型呢?取决于实现。对于Linux目前实现的NPTL实现而言,pthread_t类
型的线程ID,本质就是一个进程地址空间上的一个地址。
用户线程VSLWP
调用pthread_create,在库中创建管理块,要在内核创建轻量级进程(调用系统调用clone),既要创建出对应的控制块也要创建出对应线程,第一个参数是传入多线程函数执行的入口地址,第二个传入线程私有的独栈结构地址,这样内核数据和用户数据就联动起来了,将来执行的就是传入的这部分方法和结构,将来调函数栈帧和临时变量在线程栈里执行,CPU调度时临时数据在用户空间保存
创建多线程
#include <iostream>
#include <string>
#include <pthread.h>
#include <unistd.h>
#include <cstdio>
#include <cstring>
#include<vector>void *routine(void *args)
{ std::string name = static_cast<const char*>(args);delete (char*)args;int cnt=5;while(cnt--){std::cout<<"new线程名字"<<name<<std::endl;sleep(1);}return nullptr;
}
const int num=10;
int main()
{
std::vector<pthread_t>tids;
for(int i=0;i<num;i++)
{pthread_t tid;char* id=new char[64];snprintf(id,64,"thread-%d",i);int n=pthread_create(&tid,nullptr,routine,id);if(n==0){tids.emplace_back(tid);}elsecontinue;sleep(1);
}for(int i=0;i<num;i++){//一个一个等int n= pthread_join(tids[i],nullptr);if(n==0){std::cout<<"等待新线程成功"<<std::endl;}}return 0;
}
相关文章:
Linux线程控制
POSIX线程库 与线程有关的函数构成了一个完整的系列,绝大多数函数的名字都是以“pthread_”打头的要使用这些函数库,要通过引入头文 <pthread.h>链接这些线程函数库时要使用编译器命令的“-lpthread”选项 创建线程 功能:创建⼀个新…...
软件设计师考试《综合知识》设计模式之——工厂模式与抽象工厂模式考点分析
软件设计师考试《综合知识》工厂模式与抽象工厂模式考点分析 1. 分值占比与考察趋势(75分制) 年份题量分值占总分比例核心考点2023111.33%抽象工厂模式适用场景2022222.67%工厂方法 vs 抽象工厂区别2021111.33%工厂方法模式结构2020111.33%简单工厂模式…...
携程旅行 酒店详情 token1004 分析 phantom-token
声明 本文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关! 部分python代码 这个网站有一个坑&am…...
QT——概述
<1>, Qt概述 Qt 是⼀个 跨平台的 C 图形⽤⼾界⾯应⽤程序框架 Qt ⽀持多种开发⼯具,其中⽐较常⽤的开发⼯具有:Qt Creator、Visual Studio、Eclipse. 一,Qt Creator 集成开发环境(IDE) Qt Creator 是⼀个轻量…...
uniapp-vue3项目中引入高德地图的天气展示
前言: uniapp-vue3项目中引入高德地图的天气展示 效果: 操作步骤: 1、页面上用定义我们的 当前天气信息:<view></view> 2、引入我们的map文件 <script setup>import amapFile from ../../libs/amap-wx.js …...
最新版VSCode通过SSH远程连接Ubuntu 16.04等旧版Linux的方法
根据官方文档Remote Development FAQ - Can I run VS Code Server on older Linux distributions?,自Visual Studio Code 1.99起,VSCode Remote - SSH Server由于运行库依赖更新,会无法连接到旧版Linux发行版上。但是好在官方在文档中还给了…...
Unity碰撞检测:射线与胶囊体投射/Layer(层)、LayerMask(遮罩层)
一、Physics碰撞检测 1.Physics.Raycast射线投射 Physics.Raycast 是 Unity 中用于执行射线检测(Raycasting)的方法。它允许你从一个点沿特定方向发射一条无形的“射线”,并检查这条射线是否与场景中的任何碰撞体相交。这个功能非常有用&am…...
浪潮云边协同:赋能云计算变革的强力引擎
在数字化浪潮以排山倒海之势席卷全球的当下,第五届数字中国建设峰会在福州盛大开幕。这场以“创新驱动新变革,数字引领新格局”为主题的行业盛会,宛如一座汇聚智慧与力量的灯塔,吸引了国内外众多行业精英齐聚一堂,共同…...
“傅里叶变换算法”来检测纸箱变形的简单示例
为了创建一个具有科技质感且能动态展示结果的纸箱变形检测傅里叶变换网页,下面将分别更新 HTML、CSS 和 JavaScript 文件。以下是更新后的代码: 1. HTML 文件 (index.html) <!DOCTYPE html> <html lang"zh-CN"> <head><…...
【SPIN】用Promela验证顺序程序:从断言到SPIN实战(SPIN学习系列--2)
你写了一段自认为“天衣无缝”的程序,但如何确保它真的没有bug?靠手动测试?可能漏掉边界情况;靠直觉?更不靠谱!这时候,Promela SPIN组合就像程序的“显微镜”——用形式化验证技术,…...
如何卸载并重新安装 Mozilla Firefox 浏览器
如果你在 Windows 上遇到现有的 Mozilla FireFox 安装问题,以下是重新安装 FireFox 的步骤。这可以帮助用户解决由于某些扩展或设置问题,或者不小心下载了令人讨厌的广告软件而导致的问题。虽然现在使用 Firefox 浏览器的用户在渐渐沦为小众群体,但是 Firefox 浏览器依然是最…...
Linux 后台运行的方法
Linux 后台运行的两种方法:screen 和 nohup 使用指南 如有错误,敬请指正 方法一:使用 screen 管理后台任务(推荐) 🔹 安装(如未安装) sudo apt install screen # Ubuntu/Debian …...
《无限暖暖》画质测评
《无限暖暖》作为一款采用虚幻5引擎打造的多平台畅玩、高自由度换装探索类RPG游戏,凭借其精美的画面、沉浸式操作和暖暖美丽坚毅的人设吸引了大量玩家。 在其中玩家可以通过做各样任务收集美好并感受到丰富的人生体验,暖暖所在的世界里有超多的NPC可以互…...
websocket简介与基本使用
websocket是什么 WebSocket 是一种基于 TCP 的全双工通信协议,允许客户端和服务器之间建立持久连接,实现实时、双向的数据传输。它是 HTTP 协议的补充,专为低延迟、高效率的实时通信设计。 核心特点 特性说明全双工通信客户端和服务器可以同时…...
面试题:请解释Java中的垃圾回收机制(Garbage Collection, GC),并讨论不同的垃圾回收算法及其优缺点
Java垃圾回收机制(GC) Java的垃圾回收机制负责自动管理内存,回收不再使用的对象以释放内存空间。GC通过以下步骤实现: 标记(Marking) :识别哪些对象是可达的,哪些是不可达的。清除…...
解决 Ubuntu 22.04 安装后启动卡死问题
最近在一台 PC 上安装了 Ubuntu 22.04 系统,但发现系统启动时出现问题:屏幕上出现一个旋转的小圈,旋转片刻后停止,系统无法正常进入桌面环境。经过一番排查,我找到了一种有效的解决方法,通过进入恢复模式并…...
线程的两种实现方式
线程的两种实现方式——内核支持线程(kernal Supported Thread, KST), 用户级线程(User Level Thread, ULT) 1. 内核支持线程 顾名思义,内核支持线程即为在内核支持下的那些线程,它们的创建&am…...
Python Bug 修复案例分析:asyncio 事件循环异常引发的程序崩溃 两种修复方法
在 Python 异步编程的工作中,asyncio库为我们提供了高效处理并发任务的强大工具。然而,asyncio在使用过程中也可能因为一些细节处理不当而引发 Bug。下面,我们就来深入分析一个因asyncio事件循环异常导致程序崩溃的典型案例。兴趣的友友可以借…...
TCP(传输控制协议)建立连接的过程
TCP(传输控制协议)建立连接的过程称为 三次握手(Three-Way Handshake)。这是为了确保通信双方能够可靠地建立连接,并同步初始序列号。以下是详细步骤: 三次握手过程(通俗比喻:打电话…...
(十九)Java集合框架深度解析:从基础到高级应用
一、集合框架概述 1.1 什么是集合框架 Java集合框架(Java Collections Framework, JCF)是Java语言中用于表示和操作集合的一套标准化体系结构。它提供了一组接口、实现类和算法,用于存储和操作对象组,解决了数组在存储对象时的诸多限制。 集合框架的主…...
数据结构与算法-线性表-单链表(Linked List)
1 线性表 1.2 单链表(Linked List) 顺序表在内存中是连续的进行存储,可以随机获取某个元素,但是在插入和删除元素的时候就非常不方便,需要移动很多相关的元素,链表就可以解决这个问题。 链表就是每个节点…...
Vue3学习(组合式API——生命周期函数基础)
目录 一、Vue3组合式API中的生命周期函数。 (1)各阶段生命周期涉及函数简单介绍。 <1>创建挂载阶段的生命周期函数。 <2>更新阶段的生命周期函数。 <3>卸载阶段的生命周期函数。 <4>错误处理的生命周期函数。 (2&…...
MySQL索引优化面试高频考点解析(附实战场景)
文章目录 当索引失效成为面试官的"送命题"(必看!)高频考点一:索引失效的七大死亡陷阱1. 隐式类型转换(血泪案例!)2. 函数操作毁所有 高频考点二:最左前缀原则的魔鬼细节组…...
三目云台20倍变焦智能监控技术
“三目云台20倍转动”通常指的是一种具备三目变焦功能和20倍光学变焦能力的云台摄像机。以下是对这一概念的详细解释: 一、三目变焦功能 三目云台摄像机通常配备“长、短、广”三组定焦镜头,每组镜头都有其独特的作用: 长焦镜头 ÿ…...
SQL注入---05--跨站注入
1 权限说明 select * from mysql.user; 这里的Y表示我前面的命令权限为root,n表示不支持root权限 导致结果: 如果为root的话,我就可操作这些命令并且可以进行跨数据库攻击,但是如果不是高权限root就无法执行这些操作 2 root权限…...
AAC 协议
1. ADTS(Audio Data Transport Stream)帧结构 在ADTS(Audio Data Transport Stream)帧结构中,“上面扩展28 bit”指的是ADTS固定头(adts_fixed_header())和ADTS可变头(adts_variable_header())各自包含的28位信息。 1.1 ADTS固定头(adts_fixed_header()) AAC 帧…...
HGDB企业版迁移到HGDB安全版
文章目录 环境文档用途详细信息 环境 系统平台:Linux x86-64 Red Hat Enterprise Linux 7 版本:4.5.8,6.0 文档用途 HGDB企业版数据库通过命令备份恢复,迁移到HGDB安全版中。 详细信息 1、环境介绍 1 IP 操作系统 cpux.x.65.10 …...
智慧化系统安全分析报告
智慧化系统的安全背景与现状 一、政策法规背景 (一)全球主要国家/地区政策对比 地区政策名称核心内容实施时间特点中国《生成式人工智能服务管理暂行办法》明确服务提供者责任,强调数据合法、隐私保护,禁止生成违法内容2023年8…...
概率相关问题
问题汇总 1. 贝叶斯定理(贝叶斯公式和全概率公式)2. 概率题2.1 随机发生器的概率为1/2 1. 贝叶斯定理(贝叶斯公式和全概率公式) 定义:在信息和条件有限的情况下,基于过去的数据,通过动态调整的…...
使用 GitDiagram 快速将 GitHub 仓库转换为交互式图表
前言 当面对 GitHub 上文件目录错综复杂的新项目,且你急需快速了解其系统设计或架构流程时,你可能会感到束手无策。今天大姚给大家分享一个开源利器 GitDiagram,它可以轻松将任何复杂的 GitHub 仓库转化为直观、交互式的图表,这对…...
AWS CloudHSM:金融级密钥安全管理实战,如何通过FIPS 140-2认证守护数据生命线?
数据泄露平均成本430万美元,加密漏洞成头号杀手!当《数据安全法》撞上金融科技合规,开发者如何用硬件安全模块(HSM)构建不可破解的密钥堡垒?本文揭秘AWS CloudHSM如何成为支付系统、电子病历、区块链的“数…...
自定义分区器-基础
什么是分区 在 Spark 里,弹性分布式数据集(RDD)是核心的数据抽象,它是不可变的、可分区的、里面的元素并行计算的集合。 在 Spark 中,分区是指将数据集按照一定的规则划分成多个较小的子集,每个子集可以独立…...
<C++> MFC自动关闭对话框(MessageBoxTimeout)
MFC自动关闭对话框(MessageBoxTimeout) 记录一下今天在界面开发中的解决方案。自动关闭对话框有两种方案: 1.使用定时器实现延迟关闭(DeepSeek方案) 提示框显示几秒后自动关闭,可以使用 SetTimer KillT…...
一个基于 Spring Boot 的实现,用于代理百度 AI 的 OCR 接口
一个基于 Spring Boot 的实现,用于代理百度 AI 的 OCR 接口 BaiduAIController.javaBaiduAIConfig.java在 application.yml 或 application.properties 中添加配置:application.yml同时,需要在Spring Boot应用中配置RestTemplate:…...
Python60日基础学习打卡D26
算圆形面积 错误代码 import mathdef calculate_circle_area(r):try:S math.pi * r**2except r<0:print("半径不能为负数")return S 正确代码 import mathdef calculate_circle_area(radius):try:if radius < 0:return 0return math.pi * radius…...
报销单业务笔记
文章目录 业务点业务点-对公对私业务点-多系统标志 特殊业务入参入参报文 出参出参报文中间的逻辑多对多关系 其他应该是整体成功还是可以部分成功这种多对多关多关系有没有优雅的判断方式 报销单是个通用场景,有通用逻辑,在此基础上进行适度定制&#x…...
小红书的评论区营销经验分享
在小红书等社交平台上采用“主账号提问小号解答”的营销策略,其核心作用是通过角色分工和场景化互动,降低用户对广告的抵触心理,同时提升内容的可信度和转化效率。以下是其底层逻辑和具体作用分析: 一、角色分工:制造…...
通义灵码 2.5.4 版【**编程智能体**】初体验
一、通义灵码安装 1.VSCode通义灵码插件安装 VSCode搜索lingma,出现Lingma-Alibaba,点击安装即可,安装完毕如下图所示。 可以看到右侧版本信息如下:alibaba-cloud.tongyi-lingma版本2.5.4上次更新时间2025-05-13, 11:02:16,安装…...
2025ICPC陕西省赛题解一
L. easy 每行选能选的最小的两个,注意处理奇数的情况。 #include <bits/stdc.h> #define x first #define y second #define int long longusing namespace std; typedef unsigned long long ULL ; typedef pair<int,int> PII ; typedef pair<lon…...
java方法的练习题
方法中对自定义类型的传递 package MethodParameter.MethodParameter03;public class MP03 {public static void main(String[] args) {Person p new Person();p.m_Age 100;p.m_Name "John";B b new B();b.test02(p);System.out.println(p.m_Age p.m_Name);} }…...
【在qiankun模式下el-dropdown点击,浏览器报Failed to execute ‘getComputedStyle‘ on ‘Window‘: parameter 1 is not o
在qiankun模式下el-dropdown点击,浏览器报Failed to execute ‘getComputedStyle’ on ‘Window’: parameter 1 is not of type ‘Element’ 错误 在qiankun模式下el-dropdown点击,浏览器报Failed to execute ‘getComputedStyle’ on ‘Window’: par…...
世界模型+大模型+自动驾驶 论文小汇总
最近看了一些论文,懒得一个个写博客了,直接汇总起来 文章目录 大模型VLM-ADVLM-E2EOpenDriveVLAFASIONAD:自适应反馈的类人自动驾驶中快速和慢速思维融合系统快系统慢系统快慢结合 世界模型End-to-End Driving with Online Trajectory Evalu…...
elementUI如何动态增减表单项
设置prop的字段::prop"configs.${i}.platform" <template><el-dialogtitle"编辑配置":close-on-click-modal"false":before-close"beforeClose":visible.sync"visible"v-if"visible"class&q…...
vite运行只能访问localhost解决办法
1、找到package.json的scripts方法 2、然后指定 vite --host即可...
msf安卓远控木马手动捆绑正常apk
生成的安卓木马捆绑到正常的apk的apk中可以增强隐蔽性,有一定的过毒效果 这篇文章来讲解如何通过手动注入来实现apk的捆绑 工具:mt管理器 首先我们要明白原理:木马的payload存在于其dex文件中,将木马的payload注入到正常apk中&…...
【YOLO 系列】基于YOLO的道路坑洞检测识别系统【python源码+Pyqt5界面+数据集+训练代码】
前言 在传统的道路维护和管理中,道路坑洞的检测通常依赖人工巡查,这种方式不仅效率低下,容易出现漏检和误检的情况,而且在复杂的路况和恶劣的天气条件下,检测人员的安全也难以保障。而基于 YOLO 的道路坑洞检测系统&a…...
以项目的方式学QT开发(一)——超详细讲解(120000多字详细讲解,涵盖qt大量知识)逐步更新!
以项目的方式学QT开发 以项目的方式学QT开发 P1 QT介绍 1.1 QT简介 1.2 QT安装 1.2.1 Windows QT安装 1.2.2 QT Creator 使用基本介绍 P2 C基础 2.1 命名空间 2.1.1 命名空间作用 2.1.2 自定义命名空间 2.2 从C语言快速入门 2.2.1 输入输出 2.2.2 基…...
大模型学习
ChatTempate,Completion Only,NEFTune,SFTTrainer 微调技术 (背景:预训练后的大模型只会根据上文,输出下文,但效果不好,要微调帮他更好理解) ChatTemplate 是一种用于定…...
print()函数详解:输出文字、变量与格式化
用ChatGPT做软件测试 “掌握输出,才能掌控信息;理解输出,才能洞悉程序运行的本质。” 当我们敲下人生第一个 Python 代码: print("Hello, World!")也许并未意识到,我们接触的是整个编程世界中最基础、却也最…...
RPC与SOAP的区别
一.RPC(远程过程调用)和SOAP(简单对象访问协议)均用于实现分布式系统中的远程通信,但两者在设计理念、协议实现及应用场景上存在显著差异。 二.对比 1.设计理念 2.协议规范 3.技术特性 4.典型应用场景 5.总结 三.总结…...