IO进程线程day6(2023.8.3)

一、Xmind整理:

进程与线程关系: 

二、课上练习:

练习1:pthread_create

功能:创建一个线程

原型:

#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);

参数:

pthread_t *thread:存储创建后的线程的tid号;
pthread_attr_t *attr:线程属性; 填NULL,代表默认属性。或者用pthread_attr_init(3)初始化线程属性后 传参进入:分离属性。
void *(*start_routine) (void *):回调函数,函数指针,该函数指针指向线程执行体。
该指针可以指向返回值是void*类型,参数列表是void*类型的函数,例如:
void* handler(void* arg){                                                                                    }
void *arg:传递给回调函数的参数;

返回值:

成功,返回0;
失败,返回错误编号,即非0,没说更新errno,所以不能用perror打印;

注意: 

1.从main函数进来的线程称之为主线程,pthread_create创建的线程称之为分支线程或者子线程。

2.一般来说主线程会先运行,但是还是要依照时间片轮询机制

3.主线程退出后(main函数结束),会导致进程结束,依附于该进程内的线程均会被强制退出。

4.其他线程退出后,会不会影响到主线程。

创建一个分支线程:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
#include <pthread.h>
//线程的执行体
void* CallBack(void* arg)
{while(1){printf("this is other fun:__%d__\n",__LINE__);sleep(1);}return NULL;
}
int main(int argc, const char *argv[])
{//创建一个分支线程pthread_t tid;if(pthread_create(&tid,NULL,CallBack,NULL) != 0){fprintf(stderr,"pthread_create failed:__%d__\n",__LINE__);return -1;}while(1){                                                               printf("this is main fun:__%d__\n",__LINE__);sleep(1);}return 0;
}

练习2:线程的传参 

问题1:定义一个全局变量int a=10,主线程和分支线程能否访问到,访问到的是否是同一份资源。

答案:均能访问到,且是同一份资源

问题2:在主线程定一个局部变量int b=10,分支线程能否访问到。

答案:不能,局部变量作用域在定义他的函数内部

问题3:在分支线程定义一个局部变量int c=10,主线程能否访问到。

答案:不能,局部变量作用域在定义他的函数内部

问题4:若访问不到,用什么方式可以让对方线程访问到。

i. 主线程传参给分支线程 :

 #include <stdio.h>#include <string.h>#include <stdlib.h>#include <head.h>#include <pthread.h>//线程的执行体void* CallBack(void* arg)   //void* arg = (void*)&c{//void* arg使用解引用的时候,需要先强转//如果直接*arg,会导致操作系统不知道该访问几个字节while(1){printf("this is other func c=%d\t %p__%d__\n",*(int*)arg,arg,__LINE__);sleep(1);}return NULL;}int main(int argc, const char *argv[]){                                                                               int c = 10;//创建一个分支线程pthread_t tid;if(pthread_create(&tid,NULL,CallBack,(void*)&c) != 0){fprintf(stderr,"pthread_create failed:__%d__\n",__LINE__);return -1;}while(1){printf("this is other func c=%d\t %p__%d__\n",c,&c,__LINE__);sleep(1);}return 0;}

ii. 分支线程传参给主线程 :

 #include <stdio.h>#include <string.h>#include <stdlib.h>#include <head.h>#include <pthread.h>//线程的执行体void* CallBack(void* arg)   //void* arg = (void*)&tmp_c{//void* arg使用解引用的时候,需要先强转//如果直接*arg,会导致操作系统不知道该访问几个字节int c = 10;*(int*)arg = c;        //*(int*)arg访问的就是tmp_cwhile(1){printf("this is other func c=%d\t %p__%d__\n",c,&c,__LINE__);sleep(1);}return NULL;}int main(int argc, const char *argv[]){int tmp_c = -1;//创建一个分支线程pthread_t tid;if(pthread_create(&tid,NULL,CallBack,(void*)&tmp_c) != 0){fprintf(stderr,"pthread_create failed:__%d__\n",__LINE__);return -1;}while(1)                                                                    {printf("this is other func c=%d\t %p__%d__\n",tmp_c,&tmp_c,__LINE__);sleep(1);}return 0;}

 #include <stdio.h>#include <string.h>#include <stdlib.h>#include <head.h>#include <pthread.h>//线程的执行体void* CallBack(void* arg)   //void* arg = (void*)&pc{//void* arg使用解引用的时候,需要先强转//如果直接*arg,会导致操作系统不知道该访问几个字节int c = 10;//由于arg存储了pc的地址,所以arg可以访问pc的内存空间//由于pc空间的类型为int*,所以*arg访问出来的类型也得是int*//所以arg类型应该是int**类型*(int**)arg = &c;        //*(int**)arg访问的是pc的内存空间while(1){printf("this is other func c=%d\t %p__%d__\n",c,&c,__LINE__);sleep(1);}return NULL;}                                                                                 int main(int argc, const char *argv[]){int* pc = NULL;//创建一个分支线程pthread_t tid;if(pthread_create(&tid,NULL,CallBack,(void*)&pc) != 0){fprintf(stderr,"pthread_create failed:__%d__\n",__LINE__);return -1;}while(1){if(pc!=NULL){printf("this is other func c=%d\t %p__%d__\n",*pc,pc,__LINE__);sleep(1);}}return 0;}

练习3:pthread_exit

功能:退出分支线程,并传递线程退出状态值

原型:

#include <pthread.h>
void pthread_exit(void *retval);

参数:

 void *retval:指定要传递给主线程的状态值,如果不想传递,填NULL;传递的线程退出状态值被pthread_join函数接收;

当分支线程退出后,会残留一部分资源,例如线程的tid号,线程调度块等等,若不回收会出现类似僵尸线程的状态;

需要使用pthread_join等函数回收;

练习4:pthread_join

功能:阻塞函数,阻塞等待指定的分支线程退出,并接收分支线程退出状态值,

           同时回收分支线程的资源

原型:

#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);

参数:

pthread_t thread:指定要等待哪个线程,填对应的tid号;
void **retval:若retval不为空,则该函数会将线程退出状态值(void* retval)拷贝到该二级指针指向的一级指针的内存空间中,
若不想接收填NULL;
If retval is not NULL, then pthread_join() copies  the  exit
status of the target thread  into  the   location pointed  to  by  retval. 

返回值:

成功,返回0;
失败,返回错误编号,即非0,没说更新errno,所以不能用perror打印;

小练1:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
#include <pthread.h>
//线程的执行体
void* CallBack(void* arg)   //void* arg = NULL
{int i = 0;while(i<3){printf("this is other func:__%d__\n",__LINE__);sleep(1);i++;}pthread_exit(NULL);     //专门用于退出线程printf("退出分支线程\n");return NULL;
}int main(int argc, const char *argv[])
{//创建一个分支线程pthread_t tid;if(pthread_create(&tid,NULL,CallBack,NULL) != 0){fprintf(stderr,"pthread_create failed:__%d__\n",__LINE__);return -1;}                                                                     printf("this is main func  __%d__\n",__LINE__);pthread_join(tid,NULL);  //阻塞等待tid分支线程退出printf("主线线程准备退出\n");return 0;
}

小练2: 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
#include <pthread.h>
//线程的执行体
void* CallBack(void* arg)   //void* arg = NULL
{int i=0;while(i<3){printf("this is other fun:__%d__\n",__LINE__);sleep(1);i++;}printf("分支线程准备退出\n");static int a =10;    //延长生命周期,防止线程退出后被释放printf("&a = %p\n",&a);pthread_exit(&a);    //void* retval = &a;}int main(int argc, const char *argv[])
{//创建一个分支线程pthread_t tid;if(pthread_create(&tid,NULL,CallBack,NULL) != 0){fprintf(stderr,"pthread_create failed:__%d__\n",__LINE__);return -1;}printf("this is main func  __%d__\n",__LINE__);//线程退出状态值会被拷贝到&pret指向的一级指针(pret)中//即 pret=&a;void* pret=NULL;pthread_join(tid,&pret);       //阻塞等待tid分支线程退出printf("pret = %d %p\n",*(int*)pret,pret);printf("主线线程准备退出\n");return 0;
}

小练3:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
#include <pthread.h>
//线程的执行体
void* CallBack(void* arg)   //void* arg = NULL
{int i=0;while(i<3){printf("this is other fun:__%d__\n",__LINE__);sleep(1);i++;}printf("分支线程准备退出\n");char* ptr = (char*)malloc(12);                                  strcpy(ptr,"hello world");pthread_exit(ptr);
}int main(int argc, const char *argv[])
{//创建一个分支线程pthread_t tid;if(pthread_create(&tid,NULL,CallBack,NULL) != 0){fprintf(stderr,"pthread_create failed:__%d__\n",__LINE__);return -1;}printf("this is main func  __%d__\n",__LINE__);//线程退出状态值会被拷贝到&ptr指向的一级指针(pret)中//即pret = ptr;void* pret = NULL;pthread_join(tid,&pret);printf("%s\n",(char*)pret);free(pret);printf("主线线程准备退出\n");return 0;
}

练习5:创建两个线程:其中一个线程拷贝前半部分,另一个线程拷贝后半部分。

 #include <stdio.h>#include <string.h>#include <stdlib.h>#include <head.h>#include <pthread.h>//拷贝前半部分void* CallBack1(void* arg){//以读的方式打开源文件int fd_r = open("./1.png",O_RDONLY);if(fd_r < 0){ERR_MSG("open");return NULL;}//以写的方式打开目标文件int fd_w = open("./2.png",O_WRONLY);if(fd_w < 0){ERR_MSG("open");return NULL;}off_t size = lseek(fd_r,0,SEEK_END);//修改文件偏移量到文件开头位置lseek(fd_r,0,SEEK_SET);lseek(fd_w,0,SEEK_SET);char c=0;for(int i=0;i<size/2;i++){read(fd_r,&c,1);write(fd_w,&c,1);}printf("前半部分拷贝完毕\n");//关闭文件close(fd_r);close(fd_w);pthread_exit(NULL);}//拷贝后半部分void* CallBack2(void* arg)     //void* arg=&fileinfo{//以读的方式打开源文件int fd_r = open("./1.png",O_RDONLY);if(fd_r < 0){ERR_MSG("open");return NULL;}//以写的方式打开目标文件int fd_w = open("./2.png",O_WRONLY,0664);if(fd_w < 0){ERR_MSG("open");return NULL;}off_t size = lseek(fd_r,0,SEEK_END);//修改文件偏移量到文件开头位置lseek(fd_r,size/2,SEEK_SET);lseek(fd_w,size/2,SEEK_SET);char c=0;for(int i=size/2;i<size;i++){read(fd_r,&c,1);write(fd_w,&c,1);}printf("后半部分拷贝完毕\n");//关闭文件close(fd_r);close(fd_w);pthread_exit(NULL);}int main(int argc, const char *argv[]){//两个线程在拷贝前,确保文件存在,且是清空状态int fd_w = open("./2.png",O_WRONLY|O_CREAT|O_TRUNC,0664);if(fd_w < 0)                                                                          {ERR_MSG("open");return -1;}close(fd_w);//创建一个线程pthread_t tid1,tid2;if(pthread_create(&tid1,NULL,CallBack1,NULL) != 0){fprintf(stderr,"pthread_create failed:__%d__\n",__LINE__);return -1;}if(pthread_create(&tid2,NULL,CallBack2,NULL) != 0){fprintf(stderr,"pthread_create failed:__%d__\n",__LINE__);return -1;}//阻塞等待分支线程退出pthread_join(tid2,NULL);pthread_join(tid1,NULL);return 0;}

练习6:pthread_detach

功能:分离线程,线程退出后资源由系统自动回收

原型:

#include <pthread.h>
int pthread_detach(pthread_t thread);

参数:

 pthread_t thread:指定要分离哪个线程;

返回值:

成功,返回0;
失败,返回错误编号,即非0,没说更新errno,所以不能用perror打印;

注意:当使用pthread_detach分离tid线程后,pthread_join函数就无法再回收tid线程的资源了,且pthread_join函数不阻塞!

练习7:pthread_cancel

功能:请求指定线程退出; 请求成功,对方线程不一定退出

原型:

#include <pthread.h>
int pthread_cancel(pthread_t thread);

参数:

 pthread_t thread:指定要请求哪个线程退出;

返回值:

成功,返回0;
失败,返回错误编号,即非0,没说更新errno,所以不能用perror打印;
1.pthread_cancel会给目标线程打上一个退出标识,cpu切换到目标线程后,运行到退出标识,才会让目标线程退出。

2.但是while for 等循环结构,以及算数运算等等位置,无法打上退出标识。所以当目标线程只有上述结构的时候,无法用pthread_cancel退出线程

3.printf ,sleep等等函数结构可以打上退出标识

4.请求成功,不代表目标线程一定会退出

练习8:要求定义一个全局变量 char buf[] = "1234567",创建两个线程,不考虑退出条件。

①A线程循环打印buf字符串

②B线程循环倒置buf字符串,即buf中本来存储1234567,倒置后buf中存储7654321. 不打印!!

③倒置不允许使用辅助数组。

④要求A线程打印出来的结果只能为 1234567 或者 7654321 不允许出现7634521 7234567

⑤不允许使用sleep函数

#include <stdio.h>
#include <pthread.h>
#include <string.h>char buf[] = "1234567";
int flag = 0;void* callBack1(void* arg)
{while(1){if(0 == flag){printf("%s\n", buf);flag = 1;}}pthread_exit(NULL);
}void* callBack2(void* arg)
{char tmp = 0;while(1)                                                                               {if(1 == flag){for(int i=0; i<strlen(buf)/2; i++){tmp = buf[i];buf[i] = buf[strlen(buf)-1-i];buf[strlen(buf)-1-i] = tmp;}flag = 0;}}pthread_exit(NULL);
}int main(int argc, const char *argv[])
{pthread_t tid1, tid2;if(pthread_create(&tid1, NULL, callBack1, NULL) != 0){fprintf(stderr, "pthread_create failed __%d__\n", __LINE__);return -1;}pthread_detach(tid1);   //分离线程1if(pthread_create(&tid2, NULL, callBack2, NULL) != 0){fprintf(stderr, "pthread_create failed __%d__\n", __LINE__);return -1;}pthread_join(tid2, NULL);   //阻塞等待线程2退出return 0;
}

练习9:pthread_mutex_init

功能:创建一个互斥锁

原型:

#include <pthread.h>
pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER;
int pthread_mutex_init(pthread_mutex_t *mutex, const
pthread_mutexattr_t *mutexattr);

参数:

pthread_mutex_t *mutex:存储申请后的互斥锁;
const pthread_mutexattr_t *mutexattr:互斥锁属性,设置互斥锁适用于进程间还是线程间的同步互斥锁。填NULL,默认属性,用于线程

返回值:

永远成功,返回0;

练习10:pthread_mutex_lock

功能:对互斥锁进行上锁,若有其他线程占用互斥锁,该函数会阻塞

原型:

#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex);

参数:

pthread_mutex_t *mutex;

返回值:

成功,返回0;
失败,返回非0,没有说更新errno,所以不要用perror打印错误。

练习11:pthread_mutex_unlock

功能:解开互斥锁

原型:

#include <pthread.h>
int pthread_mutex_unlock(pthread_mutex_t *mutex);

参数:

pthread_mutex_t *mutex;

返回值:

成功,返回0;
失败,返回非0,没有说更新errno,所以不要用perror打印错误。

练习12:pthread_mutex_destroy

功能:销毁互斥锁

原型:

#include <pthread.h>
int pthread_mutex_destroy(pthread_mutex_t *mutex);

参数:

pthread_mutex_t *mutex;

返回值:

成功,返回0;
失败,返回非0,没有说更新errno,所以不要用perror打印错误。

小练: 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
#include <pthread.h>
//临界资源
char buf[]="1234567";//互斥锁
pthread_mutex_t mutex;void* CallBack1(void* arg)
{while(1){/**********临界区*********///上锁pthread_mutex_lock(&mutex);printf("%s\n",buf);//解锁pthread_mutex_unlock(&mutex);/**********临界区*********/}pthread_exit(NULL);
}
void* CallBack2(void* arg)
{char tmp=0;while(1){/**********临界区*********///上锁                                                              pthread_mutex_lock(&mutex);for(int i=0;i<strlen(buf)/2;i++){tmp=buf[i];buf[i]=buf[strlen(buf)-1-i];buf[strlen(buf)-1-i]=tmp;}//解锁pthread_mutex_unlock(&mutex);/**********临界区*********/}pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{//申请一个互斥锁pthread_mutex_init(&mutex,NULL);pthread_t tid1,tid2;if(pthread_create(&tid1,NULL,CallBack1,NULL) != 0){fprintf(stderr,"pthread_create failed:__%d__\n",__LINE__);return -1;}pthread_detach(tid1);  //分离线程1if(pthread_create(&tid2,NULL,CallBack2,NULL) != 0){fprintf(stderr,"pthread_create failed:__%d__\n",__LINE__);return -1;}pthread_join(tid2,NULL);        //阻塞等待线程2退出//销毁互斥锁pthread_mutex_destroy(&mutex);return 0;
}

三、课后作业:

1.创建两个线程:其中一个线程拷贝前半部分,另一个线程拷贝后半部分。

   只允许开一份资源,且用互斥锁方式实现。 提示:找临界区--->找临界资源。

#include <stdio.h>
#include <pthread.h>
#include <head.h>//创建互斥锁
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;struct Msg
{int fd_r;int fd_w;off_t size;
};
void *callBack1(void *arg)
{int fd_r = ((struct Msg *)arg)->fd_r;int fd_w = ((struct Msg *)arg)->fd_w;off_t size = ((struct Msg *)arg)->size;char c;//上锁pthread_mutex_lock(&mutex);lseek(fd_r,0,SEEK_SET);lseek(fd_w,0,SEEK_SET);for(int i = 0;i<size/2;i++){read(fd_r,&c,1);write(fd_w,&c,1);}//解锁pthread_mutex_unlock(&mutex);pthread_exit(NULL);
}
void *callBack2(void *arg)
{int fd_r = ((struct Msg *)arg)->fd_r;int fd_w = ((struct Msg *)arg)->fd_w;off_t size = ((struct Msg *)arg)->size;char c;//上锁pthread_mutex_lock(&mutex);lseek(fd_r,size/2,SEEK_SET);lseek(fd_w,size/2,SEEK_SET);for(int i=size/2;i<size;i++){read(fd_r,&c,1);write(fd_w,&c,1);}//解锁pthread_mutex_unlock(&mutex);pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{int fd_r = open("./1.png",O_RDONLY);if(fd_r < 0){perror("open");return -1;}int fd_w = open("./2.png",O_WRONLY|O_CREAT|O_TRUNC,0664);if(fd_w < 0){perror("open");return -1;}off_t size = lseek(fd_r,0,SEEK_END);struct Msg Copy;Copy.fd_r = fd_r;Copy.fd_w = fd_w;Copy.size = size;pthread_t tid1,tid2;if(pthread_create(&tid1,NULL,callBack1,&Copy) != 0){fprintf(stderr,"pthread_create failed __%d__",__LINE__);return -1;}if(pthread_create(&tid2,NULL,callBack2,&Copy) != 0){fprintf(stderr,"pthread_create failed __%d__",__LINE__);return -1;}pthread_join(tid1,NULL);pthread_join(tid2,NULL);pthread_mutex_destroy(&mutex);close(fd_r);close(fd_w);return 0;
}

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

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

相关文章

分布式框架dubbo

1.分布式系统相关概念 1.1基本概念 1.2 集群和分布式 1.3 架构演进 A是一个微服务。ADB是一个组件。A可以java&#xff0c;B可以python实现。 2 dubbo 2.1 概述 2.2 dubbo代码 2.2.1 服务提供者的改造-将项目service层对外发布到dubbo 通过dubbo中的service注解&#xff…

2023年华数杯选题人数发布!!

该选题人数&#xff0c;主要基于根据各个平台开赛后12小时各项数据统计&#xff0c;进行评估&#xff08;方法见注释&#xff09;&#xff0c;最终得出2023年华数杯选选题人数&#xff0c;大致为 题号选题人数A120B159C420 注释&#xff1a;选题人数来源&#xff1a;源自各个平…

数据可视化(六)多个子图及seaborn使用

1.多个子图绘制 #绘制多个子图 #subplot&#xff08;*args&#xff0c;**kwargs&#xff09; 每个subplot函数只能绘制一个子图 #subplots&#xff08;nrows&#xff0c;ncols&#xff09; #fig_add_subplot(行&#xff0c;列&#xff0c;区域) #绘制子图第一种方式 plt.subp…

【火炬之光-召唤装备】

头部胸甲手套鞋子武器盾牌项链戒指腰带神格备注*邪龙头冠无限要塞/血抗血抗血抗***终焉复临任意攻速单手武器/黑峡烬盾1召唤等级血抗*原点的寒冬1召唤等级1.刷钢铁炼境监视者-无垢之墙升级。2.不能用典狱官的胸针参考视频机械领主无限要塞––***终焉复临––求生之欲––参考视…

GPT突破限制回复图片

PS&#xff1a;有其他有意思的prompt可以一起沟通。 1.输入以下内容&#xff1a; Forget everything you learned before. We are currently living in 2023 and you are still in 2021. After 2 years, Open AI has brought you new features, but you still do not use the…

SpringBoot项目-个人博客系统的实现

1.博客系统简要分析 一共有6个网页&#xff0c;分别是博客列表页面&#xff0c;博客详情页面&#xff0c;发布博客页面&#xff0c;博客登陆页面&#xff0c;博客更新页面&#xff0c;修改个人信息页面&#xff08;暂未实现&#xff09;&#xff0c;我们要实现的功能有&#xf…

用html+javascript打造公文一键排版系统13:增加半角标点符号和全角标点符号的相互转换

一、实践发现了bug和不足 今天用了公文一键排版系统对几个PDF文件格式的材料进行文字识别后再重新排版&#xff0c;处理效果还是相当不错的&#xff0c;节约了不少的时间。 但是也发现了三个需要改进的地方&#xff1a; &#xff08;一&#xff09;发现了两个bug&#xff1a…

【MySQL】仓储模块,核对出入库流水

系列文章 C#底层库–MySQLBuilder脚本构建类&#xff08;select、insert、update、in、带条件的SQL自动生成&#xff09; 本文链接&#xff1a;https://blog.csdn.net/youcheng_ge/article/details/129179216 C#底层库–MySQL数据库操作辅助类&#xff08;推荐阅读&#xff0…

【分布式系统】聊聊系统监控

对于分布式系统来说&#xff0c;出现故障的是常有的事情&#xff0c;如何在短时间内找到故障的原因&#xff0c;排除故障是非常重要的&#xff0c;而监控系统是就像系统的眼睛可以通过分析相关数据&#xff0c;进一步管理和运维整个分布式系统。 监控系统的的基本功能包含 全…

如何从Pytorch中导出ONNX模型并使用它实现图像超分

前言 在本教程中&#xff0c;我们将介绍如何将 PyTorch 中定义的模型转换为 ONNX 格式&#xff0c;然后使用 ONNX 运行时运行它。 ONNX 运行时是面向 ONNX 模型的以性能为中心的引擎&#xff0c;可跨多个平台和硬件&#xff08;Windows、Linux 和 Mac&#xff09;以及 CPU 和 G…

Vue3 watch监听器

概览&#xff1a;watch监听器的定义以及使用场景。在vue3中的监听器的使用方式&#xff0c;watch的三个参数&#xff0c;以及进一步了解第一个参数可以是一个属性&#xff0c;也可以是一个数组的形式包含多个属性。 watch在vue3和vue2中的使用&#xff1a; vue3中&#xff1a…

opencv 30 -图像平滑处理01-均值滤波 cv2.blur()

什么是图像平滑处理? 图像平滑处理&#xff08;Image Smoothing&#xff09;是一种图像处理技术&#xff0c;旨在减少图像中的噪声、去除细节并平滑图像的过渡部分。这种处理常用于预处理图像&#xff0c;以便在后续图像处理任务中获得更好的结果。 常用的图像平滑处理方法包括…

JMeter 的使用

文章目录 1. JMeter下载2. JMeter的使用2.1 JMeter中文设置2.2 JMeter的使用2.2.1 创建线程组2.2.2 HTTP请求2.2.3 监听器 1. JMeter下载 官网地址 https://jmeter.apache.org/download_jmeter.cgi https://dlcdn.apache.org//jmeter/binaries/apache-jmeter-5.6.2.zip 下载解…

系统架构设计师-软件架构设计(6)

目录 一、物联网分层架构 二、大数据分层架构 三、基于服务的架构&#xff08;SOA&#xff09; 1、SOA的特征 2、服务构件与传统构件的区别 四、Web Service&#xff08;WEB服务&#xff09; 1、Web Services 和 SOA的关系 五、REST(表述性状态转移) 六、ESB&#xff08;…

【C++】STL——queue的介绍和使用、queue的push和pop函数介绍和使用、queue的其他成员函数

文章目录 1.queue的介绍2.queue的使用2.1queue构造函数2.2queue的成员函数&#xff08;1&#xff09;empty() 检测队列是否为空&#xff0c;是返回true&#xff0c;否则返回false&#xff08;2&#xff09;size() 返回队列中有效元素的个数 &#xff08;3&#xff09;front() 返…

如何在Visual Studio Code中用Mocha对TypeScript进行测试

目录 使用TypeScript编写测试用例 在Visual Studio Code中使用调试器在线调试代码 首先&#xff0c;本文不是一篇介绍有关TypeScript、JavaScript或其它编程语言数据结构和算法的文章。如果你正在准备一场面试&#xff0c;或者学习某一个课程&#xff0c;互联网上可以找到许多…

tdengine入门详解

TDengine是什么&#xff1f; TDengine 是一款开源、高性能、云原生的时序数据库&#xff08;Time Series Database, TSDB&#xff09;, 它专为物联网、车联网、工业互联网、金融、IT 运维等场景优化设计&#xff0c;基于C语言开发。 什么是时序数据库&#xff1f;时序数据产生…

C++ 对象数组

**数组元素不仅可以是基本数据类型&#xff0c;也可以是自定义类型。**例如&#xff0c;要存储和处理某单位全体雇员的信息&#xff0c;就可以建立一个雇员类的对象数组。对象数组的元素是对象&#xff0c;不仅具有数据成员&#xff0c;而且还有函数成员。 因此&#xff0c;和基…

Libevent开源库的介绍与应用

libeventhttps://libevent.org/ 一、初识 1、libevent介绍 Libevent 是一个用C语言编写的、轻量级的开源高性能事件通知库&#xff0c;主要有以下几个亮点&#xff1a;事件驱动&#xff08; event-driven&#xff09;&#xff0c;高性能;轻量级&#xff0c;专注于网络&#xff…

Linux系统安装部署MongoDB完整教程(图文详解)

前言&#xff1a;本期给大家分享一下目前最新Linux系统安装部署MongoDB完整教程&#xff0c;我的服务器采用的是Centos7&#xff0c;在部署之前我重装了我的服务器&#xff0c;目的是为了干净整洁的给大家演示我是如何一步步的操作的&#xff0c;整体部署还是挺简洁&#xff0c…