Linux系统编程7--线程 写个测试脚本

Linux系统编程7–线程_写个测试脚本

  • 参考博客:

    Linux多线程编程初探 - 峰子_仰望阳光 - 博客园 (cnblogs.com)

  • 我的PC是8核*16进程,所以在固定的时间点,我可以同时运行8 * 16的进程,更多的线程(任务管理器)

    Linux线程 生产者 消费者(自学)

  • sleep不会让出系统资源,只会堵了自己的线

API

请添加图片描述

0、测试脚本

  • 实验1

    //test.sh
    ./a.out
    ./a.out
    ./a.out
    
  • >>> vim test.sh  //创建脚本 测试
    >>> chmod +x test.sh
    >>> ./test.sh
    

system("echo Hello, World!")会调用系统的命令处理程序来执行echo Hello, World!命令,从而在控制台输出"Hello, World!"。

  • 第二种
  • 实验2
//demo10.c
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
int g_data = 0;//都能用它pthread_mutex_t mutex;//定义锁//	int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
void *func1(void *arg)
{pthread_mutex_lock(&mutex);//加锁//pthread_self(): 获取id,输出idprintf("t1:%ld thread is create\n",(unsigned long)pthread_self());printf("t1:param is %d\n",*((int *)arg));//输出这个函数的参数 *argwhile(1){printf("t1:%d\n",++g_data);sleep(1);if(g_data == 3){pthread_mutex_unlock(&mutex);//解锁printf("t1 quit==============================");//pthread_exit(NULL);exit(0);  //如果是exit(0),线程崩了,整个进程也会崩}}
}void *func2(void *arg)
{printf("t2:%ld thread is creat\n",(unsigned long)pthread_self());printf("t2:param is %d\n",*((int *)arg));while(1){pthread_mutex_lock(&mutex);//加锁g_data++;printf("t2:%d\n",g_data);sleep(1);pthread_mutex_unlock(&mutex);//解锁}
}int main()
{int ret;int param = 100;pthread_t t1;pthread_t t2;pthread_mutex_init(&mutex,NULL);//初始化这把锁//创造线程//返回成功时,返回线程ID给t1//第二个参数定制不同线程属性//第三个参数是要开始执行的函数//第四个参数是给上面函数的参数 param = 100;ret = pthread_create(&t1, NULL, func1,(void*)&param);//成功返回0,失败返回if(ret == 0){printf("main:creat t1 success\n");}ret = pthread_create(&t2, NULL, func2,(void*)&param);//成功返回0,失败返回if(ret == 0){printf("main:creat t2 success\n");}printf("main:%ld\n",(unsigned long)pthread_self());while(1){printf("main:creat success\n");sleep(1);}pthread_join(t1,NULL); //等待t1线程退出,否则阻塞pthread_join(t2,NULL); //等待t1线程退出,否则阻塞//可以解释为什么函数中要利用 static ;不用的话,会随机给个数传过来//printf("main:t1 quit:%d\n",*pret);pthread_mutex_destroy(&mutex);//销毁这把锁return 0;
}
//test.c  测试脚本
#include <stdlib.h>
int main()
{int i = 0;for(i = 0;i<100;i++){system("./thread");}
}
>>> gcc demo10.c -o thread
>>> gcc test.c
>>> ./a.out
>>> ./a.out >>test.ret.txt & //将运行结果放在test.ret.txt文件中//& 后台运行
>>> [2] 159894       //自动显示进程
>>> kill -9 159894   //杀死进程
>>> vim test.ret.txt //看看这个文件

1、线程的创建、退出&等待

  • 基础API

  • //线程ID获取 & 比较
    #include <pthread.h>
    pthread_t pthread_self(void);
    // 返回:调用线程的ID
    
    • 对于线程ID比较,为了可移植操作,我们不能简单地把线程ID当作整数来处理,因为不同系统对线程ID的定义可能不一样。我们应该要用下边的函数:
  • #include <pthread.h>
    int pthread_equal(pthread_t tid1, pthread_t tid2);
    // 返回:若相等则返回非0值,否则返回0
    

1.1 线程创建

#include <pthread.h>
int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
// 返回:若成功返回0,否则返回错误编号int param = 100;
ret = pthread_create(&t1, NULL, func1,(void*)&param);//成功返回0,失败返回
//返回成功时,返回线程ID给t1
//第二个参数定制不同线程属性
//第三个参数是要开始执行的函数
//第四个参数是给上面函数的参数 param = 100;

1.2 线程推出

#include <pthread.h>
int pthread_exit(void *rval_ptr);
//rval_ptr是一个无类型指针,与传给启动例程的单个参数类似。进程中的其他线程可以通过调用pthread_join函数访问到这个指针.pthread_exit((void *)p);//线程退出

1.3 线程等待

#include <pthread.h>
int pthread_join(pthread_t thread, void **rval_ptr);
// 返回:若成功返回0,否则返回错误编号pthread_join(t1,(void **)&pret); //等待t1线程退出,否则阻塞
printf("main:t1 quit:%s\n",pret);
  • 实验
#include <stdio.h>
#include <pthread.h>//	int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
void *func1(void *arg)
{//static int ret = 10;static char *p = "t1 is run out";//pthread_self(): 获取id,输出idprintf("t1:%ld thread is create\n",(unsigned long)pthread_self());printf("t1:param is %d\n",*((int *)arg));//输出这个函数的参数 *arg//pthread_exit((void *)&ret);//线程退出pthread_exit((void *)p);//线程退出
}int main()
{int ret;int param = 100;pthread_t t1;//int *pret=NULL;char *pret = NULL;//创造线程ret = pthread_create(&t1, NULL, func1,(void*)&param);//成功返回0,失败返回//返回成功时,返回线程ID给t1//第二个参数定制不同线程属性//第三个参数是要开始执行的函数//第四个参数是给上面函数的参数 param = 100;if(ret == 0){printf("main:creat t1 success\n");}printf("main:%ld\n",(unsigned long)pthread_self());pthread_join(t1,(void **)&pret); //等待t1线程退出,否则阻塞//可以解释为什么函数中要利用 static ;不用的话,会随机给个数传过来//printf("main:t1 quit:%d\n",*pret);printf("main:t1 quit:%s\n",pret);return 0;
}

2、线程共享内存

  • 实验
  • 不同的线程可以共享 g_data变量
//demo4.c
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
int g_data = 0;//都能用它//	int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
void *func1(void *arg)
{//pthread_self(): 获取id,输出idprintf("t1:%ld thread is create\n",(unsigned long)pthread_self());printf("t1:param is %d\n",*((int *)arg));//输出这个函数的参数 *argwhile(1){printf("t1:%d\n",g_data++);sleep(1);}
}void *func2(void *arg)
{printf("t2:%ld thread is creat\n",(unsigned long)pthread_self());printf("t2:param is %d\n",*((int *)arg));while(1){printf("t2:%d\n",g_data++);sleep(1);}
}int main()
{int ret;int param = 100;pthread_t t1;pthread_t t2;//创造线程				     //返回成功时,返回线程ID给t1//第二个参数定制不同线程属性    //第三个参数是要开始执行的函数//第四个参数是给上面函数的参数 param = 100;ret = pthread_create(&t1, NULL, func1,(void*)&param);//成功返回0,失败返回if(ret == 0){printf("main:creat t1 success\n");}ret = pthread_create(&t2, NULL, func2,(void*)&param);//成功返回0,失败返回if(ret == 0){printf("main:creat t2 success\n");}printf("main:%ld\n",(unsigned long)pthread_self());while(1){printf("main:creat success\n");sleep(1);}pthread_join(t1,NULL); //等待t1线程退出,否则阻塞pthread_join(t2,NULL); //等待t1线程退出,否则阻塞//可以解释为什么函数中要利用 static ;不用的话,会随机给个数传过来//printf("main:t1 quit:%d\n",*pret);return 0;
}
  • 实验结果

请添加图片描述

3、互斥锁(同步资源)

  • 互斥量 就是 一把锁;
  • 加锁—(共享资源)—解锁
  • **同步(synchronization)**是指在一定的时间内只允许某一个线程访问某个资源。而在此时间内,不允许其它的线程访问该资源。
  • 基础API

3.1 创建及销毁互斥锁

#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
int pthread_mutex_destroy(pthread_mutex_t mutex);
// 返回:若成功返回0,否则返回错误编号pthread_mutex_init(&mutex,NULL);//初始化这把锁
pthread_mutex_destroy(&mutex);//销毁锁

3.2 加锁及解锁

#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t mutex);
int pthread_mutex_unlock(pthread_mutex_t mutex);
// 返回:若成功返回0,否则返回错误编号pthread_mutex_lock(&mutex);//上锁 互斥量mutex
pthread_mutex_unlock(&mutex);//解锁
  • 实验
//demo8.c
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
int g_data = 0;
//都能用它pthread_mutex_t mutex;
//被锁锁住的都叫互斥量 mutex//	int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
void *func1(void *arg)
{pthread_mutex_lock(&mutex);//上锁 互斥量mutex//pthread_self(): 获取id,输出id、printf("t1:%ld thread is create\n",(unsigned long)pthread_self());printf("t1:param is %d\n",*((int *)arg));//输出这个函数的参数 *argpthread_mutex_unlock(&mutex);//解锁
}void *func2(void *arg)
{pthread_mutex_lock(&mutex);//上锁printf("t2:%ld thread is creat\n",(unsigned long)pthread_self());printf("t2:param is %d\n",*((int *)arg));pthread_mutex_unlock(&mutex);//解锁
}void *func3(void *arg)
{pthread_mutex_lock(&mutex);//上锁printf("t3:%ld thread is creat\n",(unsigned long)pthread_self());printf("t3:param is %d\n",*((int *)arg));pthread_mutex_unlock(&mutex);//解锁
}int main()
{int ret;int param = 100;pthread_t t1;pthread_t t2;pthread_t t3;pthread_mutex_init(&mutex,NULL);//初始化这把锁//创造线程//返回成功时,返回线程ID给t1//第二个参数定制不同线程属性//第三个参数是要开始执行的函数//第四个参数是给上面函数的参数 param = 100;ret = pthread_create(&t1, NULL, func1,(void*)&param);//成功返回0,失败返回if(ret == 0){printf("main:creat t1 success\n");}ret = pthread_create(&t2, NULL, func2,(void*)&param);//成功返回0,失败返回if(ret == 0){printf("main:creat t2 success\n");}ret = pthread_create(&t3, NULL, func3,(void*)&param);//成功返回0,失败返回if(ret == 0){printf("main:creat t3 success\n");}printf("main:%ld\n",(unsigned long)pthread_self());pthread_join(t1,NULL); //等待t1线程退出,否则阻塞pthread_join(t2,NULL); //等待t1线程退出,否则阻塞pthread_join(t3,NULL); //等待t1线程退出,否则阻塞//可以解释为什么函数中要利用 static ;不用的话,会随机给个数传过来//printf("main:t1 quit:%d\n",*pret);pthread_mutex_destroy(&mutex);//销毁锁return 0;
}
  • 实验结果

请添加图片描述

  • t1结束后,t2和t3会进行竞争,main函数没有上锁,所以可以穿插进来;

4、互斥锁限制共享资源的访问

见文首–测试脚本demo10 [Link text][#anchor-0]

5、死锁(面试)

  • 所谓死锁,是指多个进程在运行过程中因争夺资源而造成的一种僵局,当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进

  • 造成死锁的条件

    • 有两个锁
    • 线程a获得了锁1,还想要获得锁2;
    • 线程b获得了锁2,还想要获得锁1;
    //demo7
    #include <stdio.h>
    #include <pthread.h>//int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
    int g_data = 0;pthread_mutex_t mutex;
    pthread_mutex_t mutex2;void *func1(void *arg)
    {int i;pthread_mutex_lock(&mutex);sleep(1);pthread_mutex_lock(&mutex2);for(i=0;i<5;i++){printf("t1:%ld thread is create\n",(unsigned long)pthread_self());printf("t1:param is %d\n",*((int *)arg));sleep(1);}pthread_mutex_unlock(&mutex);}void *func2(void *arg)
    {pthread_mutex_lock(&mutex2);sleep(1);pthread_mutex_lock(&mutex);printf("t2:%ld thread is create\n",(unsigned long)pthread_self());printf("t2:param is %d\n",*((int *)arg));pthread_mutex_unlock(&mutex);}void *func3(void *arg)
    {pthread_mutex_lock(&mutex);printf("t3:%ld thread is create\n",(unsigned long)pthread_self());printf("t3:param is %d\n",*((int *)arg));pthread_mutex_unlock(&mutex);}int main()
    {int ret;int param = 100;pthread_t t1;pthread_t t2;pthread_t t3;pthread_mutex_init(&mutex, NULL);pthread_mutex_init(&mutex2, NULL);ret = pthread_create(&t1, NULL, func1,(void *)&param);if(ret == 0){printf("main:create t1 success\n");}ret = pthread_create(&t2, NULL, func2,(void *)&param);if(ret == 0){printf("main:create t2 success\n");}ret = pthread_create(&t3, NULL, func3,(void *)&param);printf("main:%ld\n",(unsigned long)pthread_self());pthread_join(t1,NULL);pthread_join(t2,NULL);pthread_mutex_destroy(&mutex);pthread_mutex_destroy(&mutex2);return 0;
    }
    

6、线程条件控制,实现线程的同步

  • 条件变量是线程另一可用的同步机制。条件变量给多个线程提供了一个会合的场所。
  • 动态初始化和静态初始化;二选一
//动态初始化
pthread_mutex_t mutex; //定义一把锁
pthread_cond_t cond;   //定义一个条件
//main函数里面定义
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&cond,NULL);
//静态初始化
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
//使用了静态初始化,main函数可以不用定义pthread_mutex_init(&mutex,NULL);&& pthread_cond_init(&cond,NULL);

6.1 创建及销毁条件变量

#include <pthread.h>
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t cond);
// 返回:若成功返回0,否则返回错误编号pthread_cond_init(&cond,NULL);
pthread_cond_destroy(&cond);//销毁条件
  • 除非需要创建一个非默认属性的条件变量,否则pthread_cont_init函数的attr参数可以设置为NULL

6.2 等待

#include <pthread.h>
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
// 返回:若成功返回0,否则返回错误编号pthread_cond_wait(&cond,&mutex);//等待条件发生
//cond:条件      mutex:锁
  • pthread_cond_wait等待条件变为真。如果在给定的时间内条件不能满足,那么会生成一个代表一个出错码的返回变量。

  • 传递给pthread_cond_wait互斥量(锁) 对条件进行保护,调用者把锁住的互斥量传给函数。函数把调用线程放到等待条件的线程列表上,然后对互斥量解锁,这两个操作都是原子操作。这样就关闭了条件检查和线程进入休眠状态等待条件改变这两个操作之间的时间通道,这样线程就不会错过条件的任何变化。pthread_cond_wait返回时,互斥量再次被锁住。

  • 实验

//text.c
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
//int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
int g_data = 0;
//动态初始化
pthread_mutex_t mutex;
pthread_cond_t cond;   //定义一个条件
/*
动态初始化和静态初始化;二选一
//静态初始化
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
//使用了静态初始化,main函数可以不用定义pthread_mutex_init(&mutex,NULL);&& pthread_cond_init(&cond,NULL);
*/
void *func1(void *arg)
{printf("t1:%ld thread is create\n",(unsigned long)pthread_self());printf("t1:param is %d\n",*((int *)arg));static int cnt = 0;while(1){pthread_cond_wait(&cond,&mutex);//等待条件发生//cond:条件      mutex:锁printf("t1 run================================\n");printf("t1:%d\n",g_data++);g_data = 0;sleep(1);if(cnt++ == 10){exit(1);//全退出,线程退出,全都死掉}}}void *func2(void *arg)
{printf("t2:%ld thread is create\n",(unsigned long)pthread_self());printf("t2:param is %d\n",*((int *)arg));//输出参赛 *argwhile(1){printf("t2: %d\n",g_data);pthread_mutex_lock(&mutex);g_data++;if(g_data==3){pthread_cond_signal(&cond);//触发,t1执行}pthread_mutex_unlock(&mutex);	sleep(1);}
}int main()
{int ret;int param = 100;pthread_t t1;pthread_t t2;pthread_mutex_init(&mutex,NULL);pthread_cond_init(&cond,NULL);ret = pthread_create(&t1, NULL, func1,(void *)&param);if(ret == 0){
//		printf("main:create t1 success\n");}ret = pthread_create(&t2, NULL, func2,(void *)&param);if(ret == 0){
//		printf("main:create t2 success\n");}//	printf("main:%ld\n",(unsigned long)pthread_self());pthread_join(t1,NULL);//等待pthread_join(t2,NULL);//等待pthread_mutex_destroy(&mutex);//销毁pthread_cond_destroy(&cond);//销毁条件return 0;
}
  • 结果

请添加图片描述

  • 输出到txt文件

请添加图片描述



欢迎大家一起交流讨论!

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

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

相关文章

【学习笔记】Diffusion扩散模型

导读 Diffusion models是现在人工智能领域最火的方向之一&#xff0c;并引爆了AIGC领域&#xff0c;一大批创业公司随之诞生。 AIGC&#xff08;AI-Generated Content&#xff09;&#xff1a;人工智能创作内容的生产方式。 扩散模型Diffusion 扩散模型Duffison的训练过程 …

等概率事件算法

1等概率的生成(0-8)范围内的正整数 // Math.random 数据范围[0,1) 且 是 等概率的产生随机数 // 应用&#xff1a; // 1.生成等概率的整数&#xff08;等概率的生成(0-8)范围内的正整数 int value (int) (Math.random() * 9); System.out.println("value "…

非阻塞实现高效键盘扫描功能(STM32F4XX)

目录 概述 1 原理分析 1.1 技术背景 1.2 系统硬件 1.3 STM32 IO&#xff08;输入模式&#xff09;寄存器分析 1.3.1 输入IO的功能描述 1.3.2 输入配置 1.3.3 GPIO 寄存器&#xff08;输入模式相关&#xff09; 1.3.3.1 GPIO 端口模式寄存器 1.3.3.2 GPIO 端口上拉/下拉…

springboot,druid动态数据源切换

关键字&#xff1a;springboot&#xff0c;druid数据库连接池&#xff0c;两个数据源&#xff08;可以切换成多个&#xff09;&#xff0c;事务管理 关于druid简介传送门&#xff1a;https://github.com/alibaba/druid/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98 具体分为四…

Doris【数据模型】

一、数据模型简介 在 Doris 中&#xff0c;数据以表&#xff08;Table&#xff09;的形式进行逻辑上的描述。 一张表包括行&#xff08;Row&#xff09;和列&#xff08;Column&#xff09;。Row 即用户的一行数据。Column 用于描述一行数据中不同的字段。 Column 可以分为两…

autoware.universe中跟踪模块详解,一看就懂!

目录 问题:阅读关键点:总结问题: 根据对预测模块代码的分析,发现预测框出现在点云前方的原因在于跟踪框出现在点云前方 对rviz上的目标进行观察后发现 车辆的检测框先出来一段时间后,跟踪框和预测框同步一块出来 跟踪框总是超出点云一部分 阅读关键点: 每个跟踪器最少要统计…

7.1.2 Selenium的用法1

目录 1. 初始化浏览器对象和访问页面 2. 查找节点及节点交互 2.1 查找单个节点 &#xff08;1&#xff09;获取方法1——特定方法 &#xff08;2&#xff09;通用方法 2.2 查找多个节点 2.3 节点交互 3. 动作链 4. 执行 JavaScript 之下拉进度条 5. 获取节点信息 5.…

谷歌seo推广秒收录怎么做?

谷歌SEO推广秒收录想要做到&#xff0c;可以利用我们光算科技独家技术&#xff0c;GSI快速收录&#xff0c;通过技术手段和操作&#xff0c;帮你的网站快速被谷歌发现和记录 这项技术具体核心就是GPC爬虫池系统&#xff0c;这个系统是专门研究谷歌搜索引擎优化的规律和算法创造…

66-ES6:var,let,const,函数的声明方式,函数参数,剩余函数,延展操作符,严格模式

1.JavaScript语言的执行流程 编译阶段&#xff1a;构建执行函数&#xff1b;执行阶段&#xff1a;代码依次执行 2.代码块&#xff1a;{ } 3.变量声明方式var 有声明提升&#xff0c;允许重复声明&#xff0c;声明函数级作用域 访问&#xff1a;声明后访问都是正常的&…

QT C++实现点击按键弹出窗口并显示图片/视频|多窗口应用程序的设计和开发

一、介绍 首先&#xff0c;QT界面开发中主要大体分为2种多窗口的形式&#xff1a; 嵌入式&#xff1a; 新生成的窗口嵌入在主窗口内部独立窗口&#xff1a; 以弹窗形式的新窗口生成和展示 这里就讲解最简单的&#xff1a;点击案件后&#xff0c;跳出一个新窗口 二、代码实…

利用FFMPEG 将RTSP流的音频G711 转码为AAC 并 推流到RTMP

之前我们的视频转码项目中 是没有加入音频的 现在 需要加入音频 &#xff0c;由于RTMP只支持AAC的 音频流 而有的RTSP流的音频编码并不是AAC 大多数都是G711编码 还分为G711A 和G711U 之前用ffmpeg命令行可以直接 完成转码 并推送到RTMP 但是考虑到无法获取更详细的状…

Qt篇——QTableWidget保存表格数据到Excel文件中,读Excel内容到QTableWidget

表格和excel例子如下图所示&#xff1a; 一、QTableWidget保存表格数据到Excel文件中 代码如下&#xff1a; &#xff08;pro文件中添加QT axcontainer&#xff09; #include <QAxObject>void MainWindow::saveTableToExcel() {QDateTime current_date_time QDateTi…

Vue3速成

文章目录 day 11. 创建vue3工程3. 响应式数据4. 计算属性 day 25. watch 监视6. watchEffect7. 标签的ref属性8. 回顾TS中的接口_泛型_自定义类型 day 1 1. 创建vue3工程 相关代码如下&#xff1a; ## 创建vue工程 npm create vuelastest## 安装node_modules npm install //…

JSON 文件里的 “$schema” 是干什么用的?

最近我在做一些前端项目&#xff0c;我发现有的配置文件&#xff0c;比如 .prettierrc.json 或者 tsconfig.json 里面都会看到一个 $schema 字段&#xff0c;有点好奇&#xff0c;就查了一下。 什么是 JSON Schema JSON Schema是一种基于JSON (JavaScript Object Notation) 的…

【Leetcode】2369. 检查数组是否存在有效划分

文章目录 题目思路代码结果 题目 题目链接 给你一个下标从 0 开始的整数数组 nums &#xff0c;你必须将数组划分为一个或多个 连续 子数组。 如果获得的这些子数组中每个都能满足下述条件 之一 &#xff0c;则可以称其为数组的一种 有效 划分&#xff1a; 子数组 恰 由 2 个…

大数据智能化-长视频领域

随着数字化时代的到来&#xff0c;长视频领域的发展迎来了新的机遇和挑战。在这一背景下&#xff0c;大数据智能化技术的应用成为长视频行业提升用户体验、优化运营管理的重要手段之一。本文将从优爱腾3大长视频背景需求出发&#xff0c;分析静态资源CDN、视频文件存储与分发、…

网络安全、信息安全、计算机安全,有何区别?

这三个概念都存在&#xff0c;一般人可能会混为一谈。 究竟它们之间是什么关系&#xff1f;并列&#xff1f;交叉&#xff1f; 可能从广义上来说它们都可以用来表示安全security这样一个笼统的概念。 但如果从狭义上理解&#xff0c;它们应该是有区别的&#xff0c;区别在哪呢&…

力扣hot100题解(python版36-40题)

36、二叉树的中序遍历 给定一个二叉树的根节点 root &#xff0c;返回 它的 *中序 遍历* 。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,3,2]示例 2&#xff1a; 输入&#xff1a;root [] 输出&#xff1a;[]示例 3&#xff1a; 输入&am…

【机器学习基础】层次聚类-BIRCH聚类

&#x1f680;个人主页&#xff1a;为梦而生~ 关注我一起学习吧&#xff01; &#x1f4a1;专栏&#xff1a;机器学习 欢迎订阅&#xff01;相对完整的机器学习基础教学&#xff01; ⭐特别提醒&#xff1a;针对机器学习&#xff0c;特别开始专栏&#xff1a;机器学习python实战…

matplotlib.animation 3d姿态动画

目录 演示效果&#xff1a; 演示代码&#xff1a; 保存为gif 演示效果&#xff1a; 演示代码&#xff1a; import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D from matplotlib.animation import FuncAnimation# 定义人体关键点…