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

Linux的多线程(线程的创建,退出,取消请求,取消处理例程,线程属性的设置)

进程:是系统分配资源的最小单位,系统会为每一个进程分配一块独立的虚拟内存空间

线程:是系统调度的最小单位,系统不会为线程分配新的内存空间,但是线程也参与系统调度

cpu把时间片分给每一个进程,进程中的时间片再切分分给每一个线程,所以线程也会得到时间片,所以线程使系统调度的最小单位

线程的创建

#include <pthread.h>

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                                  void *(*start_routine) (void *), void *arg);

pthread_t *thread      //线程的tid
const pthread_attr_t *attr    //线程的属性
void *(*start_routine) (void *)    //线程的任务函数
void *arg    //传递给任务函数的参数

编译时的时候记得添加  -lpthread

 void *(*start_routine) (void *) 函数指针,指向需要执行的任务函数 
 任务函数返回值必须为  void *, 参数必须为 void *,回调函数

#include <stdio.h>
#include <pthread.h>// 任务线程
void *task1(void *arg)
{int j = 0;while (1){printf("j=%d\n", j++);}
}// 任务线程
void *task2(void *arg)
{int i = 0;while (1){printf("i=%d\n", i++);}
}// 任务线程
void *task3(void *arg)
{int k = 0;while (1){printf("k=%d\n", k++);}
}int main()
{pthread_t tid1;pthread_create(&tid1, NULL, task1, NULL);pthread_t tid2;pthread_create(&tid2, NULL, task2, NULL);pthread_t tid3;pthread_create(&tid3, NULL, task3, NULL);getchar();  //调用一个阻塞函数不让进程结束
}

 线程传递参数

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>struct arg
{int a;double b;char str[1024];
} ;// 线程任务函数
void *task(void *arg)
{struct arg *p = arg;printf("整数1 %d\n", p->a);printf("浮点1 %f\n", p->b);printf("字符1 %s\n", p->str);}int main()
{struct arg arg = {15678, 156.78, "15678"};// 创建一个线程pthread_t tid;pthread_create(&tid, NULL, task, &arg);  //&arg是线程函数中的参数sleep(1);printf("整数2 %d\n", arg.a);printf("浮点2 %f\n", arg.b);printf("字符2 %s\n", arg.str);getchar(); //阻塞主进程
}

线程退出

退出当前线程

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

参数retval是线程的返回值,对应线程执行函数的返回值。若线程没有数据可返回则可写成NULL。

pthread_exit()用法可参照exit()

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>void *task(void *arg) // 子线程
{int i = 0;while (1){printf("i=%d\n", i++);sleep(1);if (i == 10){printf("退出子线程\n");pthread_exit(NULL); // 退出子线程}}
}int main() // main 主线程
{// 创建线程线程pthread_t tid;pthread_create(&tid, NULL, task, NULL);// 默认情况,主函数结束,那么进程也会结束,所有线程都会死亡!printf("退出主线程\n");pthread_exit(NULL); // 退出  main主函数线程。只是结束线程,进程并未结束// 所以就算主线程结束了子线程也还是会继续运行
}

回收一个线程资源,主线程阻塞等待子线程结束,然后回收子线程资源

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

thread: 需要回收资源的线程tid
retval:线程的退出参数,参数同上填NULL即可

通过阻塞等待线程执行完回收资源 

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>// 任务线程
void *task(void *arg)
{int i = 0; // 局部变量,属于线程的栈空间while (1){printf("线程正在执行任务 &i=%p %d\n", &i, i++);if (i == 10){pthread_exit(&i); // 退出线程}sleep(1);}
}int main()
{// 1.创建一个线程pthread_t tid;pthread_create(&tid, NULL, task, NULL);printf("等待线程结束回收资源\n");void *p = NULL;pthread_join(tid, &p); // 一直阻塞等待线程退出 ! 回收线程的栈空间printf("线程结束 退出参数:%p\n", p);printf("退出参数 %d\n", *((int *)p)); // 访问已经回收后的内存资源,非法访问!!exit(0);}

如果没有pthread_join那么线程根本不会执行完,直接在主线程中就exit(0)退出进程了


线程取消

发送一个取消命令给线程

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

thread:需要取消的线程 tid
成功返回 0,失败将返回错误码

pthread_self()   返回主线程的线程号tid

线程取消请求

        当线程收到一个取消请求时,他将会如何表现取决于两个东西:一是当前的取消状态,二是当前的取消类型。

        线程的取消状态很简单--分别是PTHREADCANCEL ENABLE和 PTHREAD CANCEL DISABLE,前者是缺省的,代表线程可以接受取消请求,后者代表关闭取消请求,不对其响应。

        而在线程接受取消请求的情况下,如何停下来又取决于两种不同的响应取消请求的策略一延时响应和立即响应,当采取延时策略时,线程并不会立即退出,而是要遇到所谓的“取消点”之后,才退出。而“取消点”,指的是一系列指定的函数。

#include <pthread.h>
int pthread_setcancelstate(int state, int *oldstate);//开启或关闭取消请求

state : 新的取消状态              PTHREAD_CANCEL_ENABLE 开启
                                               PTHREAD_CANCEL_DISABLE 关闭
oldstate:原来的状态

int pthread_setcanceltype(int type, int *oldtype); //设置取消类型

type:取消类型                                    PTHREAD_CANCEL_DEFERRED 延时取消 (默认类型)
                                                          PTHREAD_CANCEL_ASYNCHRONOUS 立即取消

返回值:成功 0

               失败errno
 

设置线程取消请求demo:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
// 任务线程
void *task(void *arg)
{// 关闭取消请求pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);int i = 0;while (1){printf("线程正在执行任务 %d\n", i++);if (i == 10){printf("执行完毕\n");break;}sleep(1);}// 开启取消请求pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);while (1){printf("线程正在运行\n");sleep(1);}
}int main()
{// 1.创建一个线程pthread_t tid;pthread_create(&tid, NULL, task, NULL);while (1){printf("输入任意键取消线程\n");getchar();pthread_cancel(tid);}
}

 在关闭线程取消请求之后,线程无法被取消,只有在重新打开线程取消请求之后的第二个循环中才能通过pthraed_cancel取消线程

线程取消处理函数

        由于线程任何时刻都有可能持有诸如互斥锁、信号量等资源,一旦被取消很有可能导致别的线程出现死锁,因此如果一条线程的确可能被取消,那么在被取消之前必须使用以下API来为将来可能出现的取消请求注册“处理例程”,让这些例程自动释放持有的资源。

注册一个取消处理函数,当线程被取消时,会去执行该函数

#include <pthread.h>
void pthread_cleanup_push(void (*routine)(void *), void *arg);

routine: 函数指针,指向线程被取消后需要执行的函数
arg:传递给取消处理函数使用的参数

void pthread_cleanup_pop(int execute);

execute: 0 不执行,线程正常结束不执行取消处理函数 
               1 执行,线程正确结束执行取消处理函数(只要线程被取消,都会执行取消处理函数)

pthread_cleanup_push必须与 pthread_cleanup_pop 一起使用,且在同一个作用域中

注册一个线程取消处理函数demo:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
FILE *fp = NULL;void clear_task(void *arg)
{printf("线程被取消,执行取消处理函数\n");fclose(fp); // 关闭文件,刷新缓存
}void *task(void *arg)
{int i = 0;// 打开文件fp = fopen("test.txt", "w+");// 注册一个取消处理函数pthread_cleanup_push(clear_task, NULL);while (1) // 正在运行的时候被别人取消了{fputc('Q', fp); // 写入文件printf("线程正在写入数据到文件中\n");sleep(1);i++;if (i == 10){break;}}//pthread_cleanup_pop(0); // 正常结束的时候,不执行pthread_cleanup_pop(1); //正常结束的时候, 执行printf("线程正常结束\n");fclose(fp); // 关闭文件,刷新缓存
}int main()
{// 1.创建一个线程pthread_t tid;pthread_create(&tid, NULL, task, NULL);while (1){printf("按任意键取消线程\n");getchar();pthread_cancel(tid);}return 0;
}

 在这段代码中当pthread_cleanup_pop中的值为1时,线程正常结束时也会执行clean_task中的函数,如果excute的值为0的话,那么只有在线程执行的过程中被打断会执行clean_task函数。

线程属性的设置

线程相关的api

 

 

查看系统的资源

loading@DESKTOP-R0NLPTR:~$ ulimit -a
real-time non-blocking time  (microseconds, -R) unlimited
core file size              (blocks, -c) 0              #core文件的最大值为100 blocks。
data seg size               (kbytes, -d) unlimited    #进程的数据段可以任意大。
scheduling priority                 (-e) 0        #调度优先级
file size                   (blocks, -f) unlimited     #文件可以任意大。
pending signals                     (-i) 25348       #最多有25348个待处理的信号。
max locked memory           (kbytes, -l) 64          #一个任务锁住的物理内存的最大值为32KB。
max memory size             (kbytes, -m) unlimited    #一个任务的常驻物理内存的最大值。
open files                          (-n) 1024        #一个任务最多可以同时打开1024的文件。
pipe size                (512 bytes, -p) 8        #管道的最大空间为4096字节。
POSIX message queues         (bytes, -q) 819200     #POSIX的消息队列的最大值为819200字节。
real-time priority                  (-r) 0
stack size                  (kbytes, -s) 8192        #进程的栈的最大值为10240字节。
cpu time                   (seconds, -t) unlimited    #进程使用的CPU时间。
max user processes                  (-u) 25348    #当前用户同时打开的进程(包括线程)的最大个数为25348。
virtual memory              (kbytes, -v) unlimited    #没有限制进程的最大地址空间。
file locks                          (-x) unlimited    #所能锁住的文件的最大个数没有限制。

设置线程属性的流程

1、初始化线程属性

2、设置线程属性

3、根据设置的线程属性创建线程

4、销毁线程和属性

线程属性也是线程创建的第二个参数

线程属性的创建和销毁

#include <pthread.h>

int pthread_attr_init(pthread_attr_t *attr);
int pthread_attr_destroy(pthread_attr_t *attr);

       

线程属性的设置

#include <pthread.h>

int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize); //设置栈大小 
int pthread_attr_getstacksize(const pthread_attr_t *attr,

                                                   size_t *stacksize);//获取栈大小

线程栈空间的设置
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>void *task(void *arg)
{int i = 0;while (1){printf("线程正在运行 %d\n", i++);sleep(1);if (i == 10){// 退出线程pthread_exit(NULL);}}
}int main()
{// 初始化一个线程属性pthread_attr_t attr;pthread_attr_init(&attr);int n;printf("请输入需要设置的线程大小\n");scanf("%d", &n);// 设置线程属性//分配的栈空间必须比系统分配最小的栈空间要大,//本机最小栈空间为16384,下文给出查看最小分配栈空间办法int size = 16384 + n;// int size = 1024;pthread_attr_setstacksize(&attr, size);// 根据当前的栈大小创建线程pthread_t tid;pthread_create(&tid, &attr, task, NULL);// 获取当前线程的栈大小size_t stacksize = 0;pthread_attr_getstacksize(&attr, &stacksize); // 获取栈大小printf("当前线程的栈大小 %ld\n", stacksize);// 回收线程资源pthread_join(tid, NULL);// 销毁属性pthread_attr_destroy(&attr);
}

获取本机当前需要分配的最小栈空间

stack_min.c

#include <stdio.h>
#include <limits.h>int main()
{printf("%d\n", PTHREAD_STACK_MIN);
}

可以看到本机的栈空间为16384

loading@DESKTOP-R0NLPTR:~/ gcc stack_min.c && ./a.out
16384
 线程分离属性设置

        一条线程如果是可接合的,意味着这条线程在退出时不会自动释放自身资源,而会成为僵尸线程,同时意味着该线程的退出值可以被其他线程获取。

        因此,如果不需要某条线程的退出值的话,那么最好将线程设置为分离状态,以保证该线程不会成为僵尸线程。

#include <pthread.h> 

int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate); 
int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate); 

detachstate: 线程分离属性           PTHREAD_CREATE_DETACHED 分离状态,自动回收资源 
                                                        PTHREAD_CREATE_JOINABLE   结合状态,手动回收资源 

注意:当一个线程设置为分离属性后,pthread_join 函数失效了! 因为该线程已经无需手动回收资源!没有返回值的函数是宏定义函数!

设置分离属性自动回收资源demo:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>void *task(void *arg)
{int i = 0;while (1){printf("线程正在运行 %d\n", i++);sleep(1);if (i == 10){// 退出线程pthread_exit(NULL);}}
}int main()
{// 初始化一个线程属性pthread_attr_t attr;pthread_attr_init(&attr);// 设置线程分离属性pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);// 根据当前的栈大小创建线程pthread_t tid;pthread_create(&tid, &attr, task, NULL);printf("等待线程结束\n");// 回收线程资源pthread_join(tid, NULL); // 失效,因为线程自己回收资源!printf("线程资源回收\n");// 销毁属性pthread_attr_destroy(&attr);getchar();}

主线程与子线程自动分离,子线程结束后,资源自动回收

#include <pthread.h>

int pthread_detach(pthread_t thread)

pthread_join()函数的替代函数,可回收创建时detachstate属性设置为PTHREAD_CREATE_JOINABLE的线程的存储空间。该函数不会阻塞父线程。pthread_join()函数用于只是应用程序在线程tid终止时回收其存储空间。如果tid尚未终止,pthread_detach()不会终止该线程

快速回收资源demo:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>void *task(void *arg)
{int i = 0;while (1){printf("线程正在运行 %d\n", i++);sleep(1);if (i == 10){// 退出线程pthread_exit(NULL);}}
}int main()
{// 根据当前的栈大小创建线程pthread_t tid;pthread_create(&tid, NULL, task, NULL);// 快速设置分离属性pthread_detach(tid);printf("等待线程结束\n");// 回收线程资源pthread_join(tid, NULL); // 失效,因为线程自己回收资源!printf("线程资源回收\n");getchar();
}

 

相关文章:

Linux的多线程(线程的创建,退出,取消请求,取消处理例程,线程属性的设置)

进程:是系统分配资源的最小单位,系统会为每一个进程分配一块独立的虚拟内存空间 线程:是系统调度的最小单位,系统不会为线程分配新的内存空间,但是线程也参与系统调度 cpu把时间片分给每一个进程&#xff0c;进程中的时间片再切分分给每一个线程&#xff0c;所以线程也会得到…...

git 本地代码关联远程仓库并推送

初始化代码仓库 如果你的本地项目还没有使用Git管理&#xff0c;首先需要在项目根目录下初始化一个Git仓库 git init添加远程仓库地址 使用 git remote add 命令添加远程仓库 git remote add origin https://github.com/username/repository.git获取远程分支信息 使用 git…...

推荐一个可以把PDF样本册转换为翻页电子书的网站

​随着互联网的普及&#xff0c;越来越多的企业和个人开始意识到线上展览的重要性。如何将实体样本册转化为线上版本&#xff0c;让更多人了解和欣赏自己的产品与服务&#xff1f; 一、网站简介 这款PDF样本册免费上传网站名为“FLBOOK”&#xff0c;致力于为广大用户提供便捷…...

【Linux 23】线程池

文章目录 &#x1f308; 一、线程池的概念&#x1f308; 二、线程池的应用场景&#x1f308; 三、线程池的实现 &#x1f308; 一、线程池的概念 线程池 (thread pool) 是一种利用池化技术的线程使用模式。 虽然创建线程的代价比创建进程的要小很多&#xff0c;但小并不意味着…...

Rust SQLite 跨平台使用

引言 Rust因其内存安全性和高性能受到越来越多开发者的青睐。在许多项目中&#xff0c;SQLite作为一种轻量级的嵌入式数据库&#xff0c;与Rust的结合为跨平台应用程序提供了强大的支持。本文将详细探讨Rust如何实现跨平台功能&#xff0c;如何在不同平台上使用Rust库&#xf…...

docker运行arm64架构的镜像、不同平台镜像构建

背景 Docker 允许开发者将应用及其依赖打包成一个轻量级、可移植的容器&#xff0c;实现“一次构建&#xff0c;到处运行”的目标。然而&#xff0c;不同的操作系统和硬件架构对容器镜像有不同的要求。例如&#xff0c;Linux 和 Windows 系统有不同的文件系统和系统调用&#…...

vue基于Spring Boot框架的高校实验室预约管理系统

目录 毕设制作流程功能和技术介绍系统实现截图开发核心技术介绍&#xff1a;使用说明开发步骤编译运行代码执行流程核心代码部分展示可行性分析软件测试详细视频演示源码获取 毕设制作流程 &#xff08;1&#xff09;与指导老师确定系统主要功能&#xff1b; &#xff08;2&am…...

Linux中find命令详解

记录linux中find命令的详细用法。 文章目录 find命令简介基本语法常用选项-name-iname-type-size-mtime,-atime,-ctime-perm-user-group-delete-exec-printand or find --help find命令简介 find 是一个搜索目录树以查找一个文件或一组文件的程序。它遍历目录树并报告与用户规…...

无水印短视频素材下载网站有哪些?十个高清无水印视频素材网站分享

你知道怎么下载无水印视频素材吗&#xff1f;今天小编就给大家推荐十个高清无水印视频素材下载的网站&#xff0c;如果你也是苦于下载高清无水印的短视频素材&#xff0c;赶紧来看看吧&#xff5e; 1. 稻虎网 首推的是稻虎网。这个网站简直就是短视频创作者的宝库。无论你需要…...

SpringBoot+Activiti7工作流入门实例

目录 文章目录 目录准备Activiti建模工具1、BPMN-js在线设计器1.1 安装1.2 使用说明1.3运行截图2、IDEA安装Activiti Designer插件2.1安装插件2.2 设置编码格式防止中文乱码2.3 截图简单工作流入门实例1. 新建Spring Boot工程2. 引入Activiti相关依赖添加版本属性指定仓库添加依…...

Azure OpenAI检索增强微调:使用 GPT-4o 对 GPT-4o mini 进行微调,以适应特定领域的应用

定制是关键&#xff01; 生成式人工智能对企业最有影响力的应用之一是创建自然语言界面&#xff0c;这些界面经过定制&#xff0c;可以使用特定领域和用例数据来提供更好、更准确的响应。这意味着回答有关特定领域的问题&#xff0c;例如银行、法律和医疗领域。 我们经常谈…...

ISP Pipeline

系列文章目录 文章目录 系列文章目录前言一、RAW域二、RGB域三、YUV域总结 前言 一、RAW域 黑电平校正&#xff08;BLC&#xff09;数字增益调整&#xff08;DGain&#xff09;自动白平衡&#xff08;AWB&#xff09;局部色调映射&#xff08;LTM&#xff09;坏点修复&#xf…...

< IDE编程环境配置>

IDE编程环境配置 LIB&#xff0c;DLL区别 我们在写项目时会链接&#xff08;调用&#xff09;第3方库&#xff0c;或者比如在vs的解决方案solution创建项目project时&#xff0c;不仅可以开发可执行程序exe&#xff08;可单独运行&#xff09;&#xff08;windows/控制台 应用…...

Golang | Leetcode Golang题解之第448题找到所有数组中消失的数字

题目&#xff1a; 题解&#xff1a; func findDisappearedNumbers(nums []int) (ans []int) {n : len(nums)for _, v : range nums {v (v - 1) % nnums[v] n}for i, v : range nums {if v < n {ans append(ans, i1)}}return }...

【Spring Boot 入门三】Spring Boot与数据库集成 - 构建数据驱动的应用

一、引言 在之前的文章中&#xff0c;我们已经对Spring Boot有了初步的认识&#xff0c;了解了如何构建第一个Spring Boot应用&#xff0c;以及如何通过配置文件来掌控应用的设置。这些知识为我们进一步探索Spring Boot与数据库的集成奠定了坚实的基础。 数据库是现代应用的核…...

Web 服务器与动态脚本语言通信的接口协议有哪些

Web 服务器与动态脚本语言通信的接口协议主要有以下几种&#xff1a; 一、FastCGI&#xff08;Fast Common Gateway Interface&#xff09; 特点&#xff1a;使用持久进程处理请求&#xff0c;减少了进程启动和关闭的开销&#xff0c;提高了性能和可扩展性。多个请求可由同一个…...

ESXI识别服务器磁盘,虚拟机显示无效

ESXI识别服务器磁盘&#xff0c;虚拟机显示无效 系统意外断电识别不到磁盘的情况下可以管理-》硬件-》搜索磁盘名称&#xff0c;选择切换直通&#xff0c;则虚拟机正常。...

【C++】 vector 迭代器失效问题

【C】 vector 迭代器失效问题 一. 迭代器失效问题分析二. 对于vector可能会导致其迭代器失效的操作有&#xff1a;1. 会引起其底层空间改变的操作&#xff0c;都有可能是迭代器失效2. 指定位置元素的删除操作--erase3. Linux下&#xff0c;g编译器对迭代器失效的检测并不是非常…...

【Spring基础3】- Spring的入门程序

目录 3-1 Spring的下载3-2 Spring的 jar 包3-3 第一个 Spring程序第一步&#xff1a;添加spring context的依赖&#xff0c;pom.xml配置如下第二步&#xff1a;添加junit依赖第三步&#xff1a;定义bean&#xff1a;User第四步&#xff1a;编写spring的配置文件&#xff1a;bea…...

golang学习笔记22-面向对象(四):接口【重要】

本节也是GO核心部分&#xff0c;很重要。 注&#xff1a;由于导包语句已经在19讲&#xff08;笔记19&#xff1a;面向对象的引入&#xff09;展示过了&#xff0c;所以这里就不展示了。 一、定义与实现 (1)接口中可以定义一组方法&#xff0c;但不需要实现&#xff0c;不需要…...

SpringBoot技术栈:打造下一代网上租赁系统

第2章 关键技术简介 2.1 Java技术 Java是一种非常常用的编程语言&#xff0c;在全球编程语言排行版上总是前三。在方兴未艾的计算机技术发展历程中&#xff0c;Java的身影无处不在&#xff0c;并且拥有旺盛的生命力。Java的跨平台能力十分强大&#xff0c;只需一次编译&#xf…...

Vue-Lecture1-Notes

渐进式框架 Vue 被称为“渐进式框架”&#xff0c;是因为它允许开发者根据项目的需求逐步引入和使用其功能&#xff0c;而不需要一次性使用整个框架。简单来说&#xff0c;Vue 提供了从简单到复杂的功能层次&#xff0c;可以灵活选择使用。 按需使用&#xff1a;Vue 的核心功能…...

网上租赁系统开发:SpringBoot实践与应用

第2章 关键技术简介 2.1 Java技术 Java是一种非常常用的编程语言&#xff0c;在全球编程语言排行版上总是前三。在方兴未艾的计算机技术发展历程中&#xff0c;Java的身影无处不在&#xff0c;并且拥有旺盛的生命力。Java的跨平台能力十分强大&#xff0c;只需一次编译&#xf…...

User-Agent在WebMagic爬虫中的重要性

对于需要从网站上抓取数据的开发者来说&#xff0c;WebMagic是一个强大的工具。它是一个简单灵活的Java爬虫框架&#xff0c;用于抓取网页数据。在爬虫技术中&#xff0c;User-Agent&#xff08;用户代理&#xff09;是一个关键的HTTP请求头&#xff0c;它告诉服务器关于客户端…...

如何解决 Docker 下载 mcr.microsoft.com 镜像慢的办法

一、介绍 MCR(Miscrosoft Container Registry) 加速器&#xff0c;助你在中国大陆急速下载 netcore 相关的 docker 镜像。二、解决办法。     1、如何使用       至少三种方法进行加速&#xff1a;         使用 docker-mcr &#xff08;推荐&#xff09;  …...

网络编程,端口号,网络字节序,udp

前面一篇我们讲了网络的基础&#xff0c;网络协议栈是什么样的&#xff0c;数据如何流动传输的&#xff1b;接下来这篇&#xff0c;我们将进行实践操作&#xff0c;真正的让数据跨网络进行传输&#xff1b; 1.网络编程储备知识 1.1 初步认识网络编程 首先我们需要知道我们的…...

Android入门

下载Android studio&#xff0c;创建第一个项目 模板可以选择empty views Activity 在这个界面可以修改&#xff0c;使用语言&#xff0c;项目名字&#xff0c;存储路径以及适用版本 完成后&#xff0c;得到一个最初始的Android 项目&#xff0c;红色标记的两个文件&#xf…...

二叉树深搜专题篇

目录 计算布尔二叉树的值 求根节点到叶节点数字之和 二叉树剪枝 验证二叉搜索树 二叉搜索树中第K小的元素 二叉树的所有路径 计算布尔二叉树的值 题目 思路 这道题其实是比较简单的&#xff0c;对二叉树来一次后序遍历即可&#xff0c;当遇到叶子结点直接返回叶子节点中…...

堆【数据结构C语言版】【 详解】

目录-笔记整理 一、思考二、堆概念与性质三、堆的构建、删除、添加1. 构建2. 删除3. 添加 四、复杂度分析4.1 时间复杂度4.2 空间复杂度 五、总结 一、思考 设计一种数据结构&#xff0c;来存放整数&#xff0c;要求三个接口&#xff1a; 1&#xff09;获取序列中的最值&#…...

初识React

在最新写需求的时候&#xff0c;我遇到了一个需求&#xff0c;这个需求改后端改的不算多&#xff0c;而且也比较简单&#xff0c;但是在改前端的时候&#xff0c;很复杂。因为我们这个项目用的是React做前端的&#xff0c;而我对于前端知识没有了解&#xff0c;所以理解很多代码…...

二级网站怎么建设/学校网站建设

http://www.yiibai.com/html/testng/2013/0914296.html 本教程介绍了TestNG中执行程序的方法&#xff0c;这意味着该方法被称为第一和一个接着。下面是执行程序的TestNG测试API的方法的例子。 创建一个Java类文件名TestngAnnotation.java在C:\>TestNG_WORKSPACE测试注解。 i…...

wordpress 固定链接结构出错/网络优化器下载

距离矢量&#xff08;Distance Vector&#xff09;说法是因为路由是以矢量&#xff08;距离、方向&#xff09;的方式通告出去的&#xff0c;其中距离是根据度量定义的&#xff0c;方向是根据下一跳路由器定义的。因此&#xff0c;满足距离矢量路由选择协议的条件要有两条&…...

做旅游网站会遇到什么问题/友情连接

我本来给图片设置了object-fit&#xff1a;cover; 但是 html2canvas画完之后 竟然消失了 这个就很奇怪了&#xff0c;包括图片的圆角也没有了&#xff0c; 我翻了翻一些文档说 子元素设置相对于父元素宽高 然后在设置object-fit &#xff08;我试了试不行pass掉了&#xff09…...

wordpress房地产插件/教育培训机构有哪些

2019独角兽企业重金招聘Python工程师标准>>> 在开始菜单中找到vmware 安装文件夹点击虚拟网络编辑器&#xff1b;查看子网掩码和网关地址&#xff0c;选中vmnet8,点击nat设置 。获取子网掩码255.255.255.0&#xff0c;网关192.168.199.2点击dhcp设置&#xff0c;获取…...

wordpress建站模板/宁波专业seo服务

在.NET环境中&#xff0c;非托管系统资源由开发人员来负责释放&#xff0c;且非托管系统资源必须显式的使用IDisposable接口的Dispose()来释放(详见&#xff1a;了解.NET内存管理机制)。所有封装或使用了非托管资源的类型都实现了IDisposable接口。同时这些类也在终结器中调用D…...

58同城保定网站建设/企业站seo价格

问题 Image和Label数据成对写入TFRecord文件&#xff0c;按理训练过程中读取的Image和Label也应该是一一对应的&#xff0c;但有的时候发现Image和Label并不能匹配。如&#xff1a; 将以下数据写入TFrecord中&#xff1a; Image 1 —— Label 1 Image 2 —— Label 2 Image …...