目录
1.memcpy
2.memmove
3.memset
4.memcmp
以下都是内存函数,作用单位均是字节
1.memcpy memcpy是C/C++语言中的一个内存拷贝函数,其原型为:
void* memcpy(void* dest, const void* src, size_t n); 目标空间(字节) 源空间(字节) 拷贝个数 该函数的功能是将源地址src开始的n个字节内容复制到目标地址dest开始的内存空间。 使用memcpy函数需要注意以下几点:
要确保目标地址dest有足够的空间来存放从源地址src复制过来的数据,否则可能会发生内存溢出。要确保源地址src和目标地址dest指向的内存内容是可读写的。在使用该函数时需要注意边界情况,即源地址src和目标地址dest的有效数据范围。 接下来,我们观察memcpy函数:
#include <stdio.h> #include <string.h> int main() { const char* src = "Hello, memcpy!"; char dest[20]; // 复制字符串到dest中 memcpy(dest, src, strlen(src) + 1); // 输出复制后的字符串 printf("Copied string: %s\n", dest); return 0; } 程序运行结果:
Copied string: Hello, memcpy! 很显然,源字符串“Hello, memcpy!”已成功被复制到了目标字符数组dest中。
现在,我们来观察memcpy函数的实现方式:
//Memcpy #include<stdio.h> #include<assert.h> void* Memcpy(void* dest, const void* src, size_t byte_num) { assert(dest && src); char* ptr_1 = (char*)dest; const char* ptr_2 = (const char*)src; while (byte_num) { *ptr_1 = *ptr_2; ptr_1++; ptr_2++; byte_num--; } return dest;//返回指向目标内存块的指针。 } int main() { int arr[] = { 1,2,3,4,5,6,7,8,9,0 }; int src[] = { 8,8,8,8,8,8,8,8,8,8 }; Memcpy(arr, src, 15); for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) { printf("
一、React简介
1、React是Facebook开发的一款JS库。
2、React一般被用来作为MVC中的V层,它不依赖其他任何的库,因此开发中,可以与任何其他的库集成使用,包括Jquery、Backbone等。
3、它可以在浏览器端运行,也可以通过nodejs在服务端渲染。
4、React的思想非常独特,性能出众,可以写出重复代码少,逻辑清晰的前端代码。
5、React的语法是jsx,通过使用这种语法,可以在react代码中直接混合使用js和html来编写代码,这样代码的逻辑就非常清晰,当然也意味着,需要将jsx代码编译成普通的javascript代码,才能在浏览器中运行,这个过程根据实际项目情况,可以选择多种不同的思路,或者在服务器端通过webpack进行编译。
1、 声明式设计 -React采用声明范式,可以轻松描述应用。
2、以组件的方式开发
3、使用特殊的jsx(JavaScript XML)语法
4.、高效 -React通过对DOM的模拟使用了虚拟DOM,最大限度地减少与DOM的交互
<div> { this.state.s.title } <ul> { this.state.list.map((item,index)=>{ return <li key={ index } > { item } </li> }) } </ul> </div> JSX是一种JavaScript的语法扩展,运用于React架构中,其格式比较像是模版语言,但事实上完全是在JavaScript内部实现的。元素是构成React应用的最小单位,JSX就是用来声明React当中的元素,React使用JSX来描述用户界面。
React的优点有哪些:单向数据流、兼容性好、速度快!
二、项目结构
├─ myreactapp ├─ README.md ├─ package-lock.json ├─ package.json ├─ public │ ├─ favicon.ico │ ├─ index.html │ ├─ logo192.png │ ├─ logo512.png │ ├─ manifest.json │ └─ robots.txt └─ src ├─ App.
本篇文章记录我学习FreeRTOS队列创建的知识。主要分享队列创建需要使用的初始化函数、队列复位函数。
需要进一步了解FreeRTOS队列的相关知识,读者可以参考以下文章:
FreeRTOS学习——FreeRTOS队列(上)_freertos 单元素队列-CSDN博客
FreeRTOS学习——FreeR TOS队列——队列创建(中)-CSDN博客
一、队列初始化函数 队列初始化函数prvInitialiseNewQueue()用于队列的初始化,此函数在文件queue.c中有定义,函数代码如下:
(1)、队列结构体中的成员变量pcHead指向队列存储区中首地址。
(2)、初始化队列结构体中的成员变量uxQueueLength和uxItemSize,这两个成员变量保存队列的最大队列项目和每个队列项大小。
(3)、调用函数xQueueGenericReset()复位队列。PS:发一句牢骚,绕来绕去的,函数调了一个又一个的。
二、队列复位函数 队列初始化函数 prvInitialiseNewQueue()中调用了函数xQueueGenericReset()来复位队列,函数xQueueGenericReset()代码如下:
(1)、初始化队列中的相关成员变量。
(2)、根据参数xNewQueue确定要复位的队列是否是新创建的队列,如果不是的话还需要做其他的处理
(3)、初始化队列中的列表xTasksWaitingToSend和 xTasksWaitingToReceive。
至此,队列创建成功,比如我们创建一个有4个队列项,每个队列项长度为32个字节的队列TestQueue,创建成功的队列如下:
# 昨日知识点回顾
制定规范、创建虚拟环境并激活,正在虚拟环境创建项目、数据库和应用程序
# 今日知识点学习
18.2.4 定义模型Entry
# models.py from django.db import models # Create your models here. class Topic(models.Model): """用户学习的主题""" # 存储少量文本如名称、标题或城市,预留200字符空间 text = models.CharField(max_length=200) # 记录日期和时间的数据,为True自动设置为当前日期和时间 data_added = models.DateTimeField(auto_now_add=True) class Entry(models.Model): """学到某个主题的具体知识""" topic = models.ForeignKey(Topic, on_delete=models.CASCADE) # 外键(foreign key)是一个数据库术语,它指向数据库另一条记录。 # 次联删除:on_delete=models.CASCADE让Django在删除主题的同时删除所有与之相关联的条目 text = models.TextField() date_added = models.DateTimeField(auto_now_add=True) class Meta: # 存储用于管理模型的额外信息 verbose_name_plural = 'entries' def __str__(self): """返回模型的字符串表示""" # 只显示条目前50字符,省略号指出显示的并非整个条目 return f"{self.text[:50]}..." 18.2.5 迁移模型Entry
18.2.6 向管理网站注册Entry
# admin.py from django.
vector(上):C++初阶学习第八弹——探索STL奥秘(三)——深入刨析vector的使用-CSDN博客
vector(中):C++初阶学习第九弹——探索STL奥秘(四)——vector的深层挖掘和模拟实现-CSDN博客
目录
一、vector的迭代器失效问题的本质
二、vector迭代器失效的原因
1、引起底层空间改变的操作
2、进行指定元素删除的时候—erase
3、在其他编译环境下的失效情况
4、string的迭代器失效
三、vector迭代器失效的解决方法
四、总结
前言:
在前面我们已经学习了vector的使用和其模拟实现,相信也帮助我们了解了vector这个容器的基本规则,但其实在我们讲解的过程中,有一些知识点我们还没提到,今天,我们就专门来讲一下vector在使用和模拟实现的过程中一个容易出错的知识点——迭代器失效问题
一、vector的迭代器失效问题的本质 迭代器的作用就是能让我们忽略变量的类型,方便我们访问,其本质其实还是指针,类如对于vector的类型的,++后往后访问其实也是将指针改为指向下一个数据的指针,迭代器失效就是迭代器底层使用的指针指向的空间被释放了,这样再使用这个迭代器就会造成程序崩溃,这就是迭代器失效(迭代器失效也与编译环境有一定关系)
二、vector迭代器失效的原因 vector容器可能会发生迭代器失效的操作有以下几种:
1、引起底层空间改变的操作 比如resize、reserve、insert、assign、push_back等
例如:
#include<iostream> #include<vector> using namespace std; int main() { vector<int> v{ 1,2,3,4,5,6 }; auto it = v.begin(); while (it != v.end()) { cout << *it << " "; ++it; } cout << endl; return 0; } 对于这样一个程序,我们定义了一个v,并用迭代器来实现全部访问,运行结果如下: 在这个程序中,我们记录下了v的begin迭代器,并一步步向后走,从而实现遍历,但我们知道vector的本质上与顺序表是类似的, 它是在内存上找一段能放下当前数据的空间,但是当我们进行扩容等操作的时候的时候,可能原空间下就不够用了,就需要找一个新的位置开辟空间并且销毁旧空间,这个时候迭代器指向的位置就会发生变化,而it还记录的原来begin指向原来的那段空间,所以就会导致程序崩溃,出现迭代器失效的现象 例如(错误示范): #include<iostream> #include<vector> using namespace std; int main() { vector<int> v{ 1,2,3,4,5,6 }; auto it = v.
已排查:1.ufw status 防火墙已关闭 2.selinux已关闭 3.netstat -ntpl :::8088 未限制ip
问题:docker swarm多主机之间的端口无法访问,但能ping通,同一主机下的端口也可以访问。
原因:docker overlay网络内部使用vxlan技术实现网络内部互通,通过 udp 4789 端口进行流量转发,此端口可以在swarm初始化时修改。
解决:tcpdump每台机器物理网卡的4789端口的流量:tcpdump -i ens160 udp port 4789 -vv -X;
在worker节点上访问manager节点的tcp 9999服务,可以看到如下报文:
tcpdump: listening on ens160, link-type EN10MB (Ethernet), capture size 262144 bytes
13:40:49.011232 IP (tos 0x0, ttl 64, id 25866, offset 0, flags [none], proto UDP (17), length 110)
master-01.41787 > 10.168.1.181.4789: [bad udp cksum 0x174d -> 0x4773!] UDP, length 82
0x0000: 4500 006e 650a 0000 4011 fcc6 0aa8 01aa E.
四种模式介绍 宿主机可上网,容器内便可上网.且能ping通宿主机同网段服务
Docker网络模式
配置
说明
host模式
--net=host
容器和宿主机共享Network namespace。
container模式
--net=container:NAME_or_ID
容器和另外一个容器共享Network namespace。 kubernetes中的pod就是多个容器共享一个Network namespace。
none模式
--net=none
容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配veth pair 和网桥连接,配置IP等。
bridge模式
--net=bridge
(默认为该模式)
host模式
如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。
使用 --net=host 模式由于直接使用宿主机ip和端口,无需-p 手动映射端口了
container模式
这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。
none模式
使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。
这种网络模式下容器只有lo回环网络,没有其他网卡。none模式可以在容器创建时通过--network=none来指定。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。
bridge模式(桥接模式,和宿主机处于同一网段)
当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥(桥接网络ifconfig docker0),此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中,形成一个局域网(LAN),容器之间包括宿主机可以通过docker容器虚拟ip互相通讯。但想从不同主机访问容器需暴露到主机端口。想让跨主机间容器可以互相通讯需安装weave、fannel等跨主机网络通讯插件,用weave分配容器ip,这样跨主机容器间才可用ip互相通讯了,否则其他主机(包括其他主机的容器)通过容器ip访问不到docker容器,因为docker0是172.0.0.1(localhost),其分配的容器ip也是172.0.0.2等,仅与本机属于同一网段。
在默认的bridge模式下,docker0网络的默认网关即是宿主机。在Linux下,docker0网络通常会分配一个172.17.0.0/16的网段,其网关通常为172.17.0.1(localhost);macOS下的网段则为192.168.65.0/24,网关为192.168.65.1。在容器中使用该网关IP地址即可访问宿主机上的各种服务(直接使用宿主机ip也可以)。注意:经由docker0网桥而来的流量不经过宿主机的本地回环,容器经由docker0网桥无法访问到监听地址是127.0.0.1(localhost)的应用,因此需要将宿主机上的应用(MySQL,Redis等)配置为监听0.0.0.0。
从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备,Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过brctl show命令查看。
bridge模式是docker的默认网络模式(k8s pod中的docker默认是container模式),不写--net参数,就是bridge模式。使用docker run -p时,docker实际是在iptables做了DNAT规则,实现端口转发功能。可以使用iptables -t nat -vnL查看。
在安装一些python的软件包时,经常安装错误,可能是跟python的位数有关系。
下面告诉大家如何查看python的位数。
第一种方法:通过在cmd中输入“python”即可。
第二种方法:通过platform包查看,首先导入platform包,然后输入“platform.architecture()”即可。
即可看到是32bit。
以上就是两种查看python版本位数的办法。
1.信号入门 1.1生活中的信号 什么是信号?
结合实际红绿灯、闹钟、游戏中的"!"等等这些都是信号。
以红绿灯为例子:
一看到红绿灯我们就知道:红灯停、绿灯行;我们不仅知道它是一个红绿灯而且知道当其出现不同的状况时我们应该做出怎么样的行为去应对。
识别=认识+行为产生
对于红绿灯:
我们之前受过的教育,让我们能够识别这个红绿灯(即使它还未出现在我们眼前),也就是说你能识别"红绿灯"
当绿灯量了后我们不一定要直接走,也可以等一会再走(也就是说接收信号后我们不一定要立刻产生对应的行为)
当红灯亮了之后,我们可以玩手机,要记得这个时候还是红灯
当红或绿灯亮时我们可以做出其他行为,也可以忽略红绿灯
对于信号来说(进程看待信号的方式)
在没有发生的时候,进程已经知道发生的时候该怎么处理了信号进程能够认识,在遇见信号之前有人在"大脑"中设置了识别特定信号的方式(进程能够识别一个信号并处理)信号到来的时候,进程正在处理更重要的事情,这时进程暂时不能立即处理到来的信号,进程必须暂时将到来的信号进行临时保存信号到了进程可以不立即处理,等在合适的时候处理信号的产生是随时产生的,进程无法准确预料,所以信号是异步发送的(信号的产生是由别人(用户、进程)产生的,在进程收到信号之前,进程一直在忙自己的事情,并发在跑的) 为什么?
停止、删除...系统要求进程要有随时响应外部信号的能力,随后做出反应
我们学习信号是学习它的整个生命周期,在进程运行期间信号的生命周期分为以下几个阶段:
准备、信号的产生、信号的保存、信号的处理
1.2Linux中的信号 用户输入命令,在Shell下启动一个前台进程
用户按下 Ctrl-C ,这个键盘输入产生一个硬件中断,被OS获取,解释成信号,发送给目标前台进程
前台进程因为收到信号,进而引起进程退出
#include<iostream> #include<unistd.h> using namespace std; int main() { while(1) { cout<<"i am main process..."<<endl; sleep(1); } return 0; } Ctrl-C 产生的信号只能发给前台进程。一个命令后面加个&可以放到后台运行,这样Shell不必等待进程结束就可以接受新的命令,启动新的进程。Shell可以同时运行一个前台进程和任意多个后台进程,只有前台进程才能接到像 Ctrl-C 这种控制键产生的信号。前台进程在运行过程中用户随时可能按下 Ctrl-C 而产生一个信号,也就是说该进程的用户空间代码执行到任何地方都有可能收到 SIGINT 信号而终止,所以信号相对于进程的控制流程来说是异步(Asynchronous)的。 1.3信号的概念 信号是进程之间事件异步通知的一种方式,属于软中断
在Linux操作系统中命令:kill -l可以查看系统定义的信号列表 上面的数字和名字都可以标识信号,名字其实就是宏;总共62个信号(没有0、32、33信号)
其中:1~31号是普通信号 34~64是实时信号
我们这里只学普通信号
上面我们说到:每个信号都有一个编号和一个宏定义名称,这些宏定义名称可以在signal.h中找到,这些信号各自在什么条件下产生,默认的处理动作是什么,在signal(7)中都有详细说明: man 7 signal 根据我们对Linux的了解,信号存放在哪呢?既然信号是给进程的,而进程又是通过内核数据结构来管理的,那么我们可以推断出,信号是放在进程的task_struct结构体中
既然他是在PCB中,如果创建31变量把信号全存进去,那就太浪费了;进程中信号的状态分为有或者没有,那么我们可以大胆的推断:把31个信号存放在一个只有32位整型变量中,每一个比特位都代表一个信号。
比特位的位置,代表信号的编号
比特位的内容:代表进程是否收到信号,1表收到,0表没收到
那么问题来了,内核数据结构的修改,这是由谁来完成的?
毫无疑问,是操作系统,毕竟task_struct就是由它来维护的,只有OS才有权利去修改它
1、快捷键 强制停止ctrl + c退出或登出ctrl + d查看历史输入过的命令history命令自动执行上一次匹配前缀的命令!命令前缀输入内容去匹配历史命令ctrl + r光标移动快捷键 ctrl + a,跳到命令开头
ctrl + ← | →,左右跳单词
清屏 ctrl + l
clear 命令
2、软件安装 yum [-y] [ install | remove | search] 软件名称
yum:RPM包软件管理器,用于自动安装配置Linux软件,并可以自动解决依赖问题-y:自动确认安装或卸载过程 需要root权限 3、控制软件的状态 systemctl start |stop |status |enable |disable 服务名 start 启动、stop 关闭、status 查看状态、enable 开启开机自启、disable 关闭开机自启系统内置服务:NetworkManager-主网络服务、network-副网络服务、firewalld-防火墙服务sshd-ssh服务(FinallShell远程登录Linux使用的就是这个服务)除内置服务以外,部分第三方软件安装后也可以以systemctl进行控制 yum install -y ntp,安装ntp软件,可以通过ntpd服务名,配合systemctl进行控制yum install -y httpd,安装apache服务器软件,可以通过httpd服务名,配合systemctl进行控制部分软件安装后没有自动集成到systemctl中,我们可以手动添加 4、创建软连接 ln -s 被链接的文件(夹) 目的地 链接只是一个指向,并不是物理移动,类似Windows系统的快捷方式
ln -s /etc/yum.conf ~/yum.conf
5、查看日期时间 date [-d] [+格式化字符串] 2024-05-21 21:58 格式:"
1.基本查找/顺序查找
核心:从0索引之后挨个查找
实现代码:
public class test { public static void main(String [] arg) throws ParseException { int[] arr= {121,85,46,15,55,77,63,49}; int number=55; System.out.println(bashi(arr,number)); } public static boolean bashi(int []arr,int number) { for(int i=0;i<arr.length;i++) { if(number==arr[i]) { return true; } } return false; } } 查找某个数据的索引,若考虑数据重复问题,则需要使用集合,将数据索引放入集合中。
public class test { public static void main(String [] arg) throws ParseException { //返回数据的索引,需要考虑数据重复问题 int[] arr= {121,85,46,15,55,77,63,49,55}; int number=55; System.out.println(bashi(arr,number)); } public static ArrayList<Integer> bashi(int []arr, int number) { ArrayList<Integer> list=new ArrayList(); for(int i=0;i<arr.
🧑 博主简介:阿里巴巴嵌入式技术专家,深耕嵌入式+人工智能领域,具备多年的嵌入式硬件产品研发管理经验。
📒 博客介绍:分享嵌入式开发领域的相关知识、经验、思考和感悟,欢迎关注。提供嵌入式方向的学习指导、简历面试辅导、技术架构设计优化、开发外包等服务,有需要可加文末联系方式联系。
💬 博主粉丝群介绍:① 群内高中生、本科生、研究生、博士生遍布,可互相学习,交流困惑。② 热榜top10的常客也在群里,也有数不清的万粉大佬,可以交流写作技巧,上榜经验,涨粉秘籍。③ 群内也有职场精英,大厂大佬,可交流技术、面试、找工作的经验。④ 进群免费赠送写作秘籍一份,助你由写作小白晋升为创作大佬。⑤ 进群赠送CSDN评论防封脚本,送真活跃粉丝,助你提升文章热度。有兴趣的加文末联系方式,备注自己的CSDN昵称,拉你进群,互相学习共同进步。
本地搭建类ChatGPT项目GPT4free并使用公网地址远程AI聊天 1. 前言:人工智能与绿色未来的交汇点2. 相关概念与背景介绍2.1 机器学习基础2.2 环境保护的挑战2.3 机器学习与环保的融合 3. 应用场景分析3.1 气候预测与天气模式识别3.1.1 概述3.1.2 示例:使用LSTM进行气候预测 3.2 环境污染监测与管理3.2.1 概述3.2.2 示例:基于聚类分析的污染源识别 3.3 生物多样性保护3.3.1 概述3.3.2 示例:卷积神经网络(CNN)识别野生动物 5. 机器学习应用场景的深化5.1 强化学习在资源管理中的应用5.1.1 概述5.1.2 示例:智能水资源管理系统 5.2 集成学习在污染预测中的优势5.2.1 概述5.2.2 示例:GBM预测空气污染指数5.2.3 示例:随机森林预测空气污染指数(Python代码示例) 5.3 深度学习在环境图像识别中的应用5.3.1 概述5.3.2 示例:卫星图像分析森林砍伐5.3.3 示例:使用卷积神经网络识别森林砍伐(Python代码示例,基于Keras) 5.4 自然语言处理(NLP)在环境政策分析中的作用5.4.1 概述5.4.2 示例:情感分析评估公众环保意识5.4.3 示例代码 6. 总结:机器学习,绿色地球的智慧引擎 1. 前言:人工智能与绿色未来的交汇点 在这个全球气候变化日益严峻的时代,环境保护已成为人类面临的重大挑战之一。科技的发展,特别是人工智能(AI)和机器学习(ML)的崛起,为我们提供了前所未有的工具,去应对这些挑战。机器学习,凭借其在数据处理、模式识别和预测分析方面的强大能力,正逐渐成为环境保护领域的一股变革力量。本文将深入探讨机器学习如何赋能环境保护,通过分析气候数据、环境传感器数据,进行气候预测、天气模式识别,以及监测和减少环境污染,描绘出一幅利用技术守护地球的蓝图。
2. 相关概念与背景介绍 2.1 机器学习基础 机器学习是一种人工智能技术,它使计算机系统能够在不进行明确编程的情况下从数据中学习并改进其表现。通过训练模型,机器学习可以识别模式、做出预测、甚至自我优化,其核心在于算法、数据和计算能力的结合。
2.2 环境保护的挑战 环境保护面临的问题包括但不限于气候变化、空气和水污染、生物多样性丧失等。这些问题复杂且相互关联,需要综合性的解决方案。传统方法受限于数据收集和分析的难度,往往难以提供及时有效的干预措施。
2.3 机器学习与环保的融合 机器学习在环境保护中的应用,主要体现在以下几个方面:通过对海量环境数据的分析,识别环境变化的趋势和模式;预测极端天气事件,提高灾害预警的准确性;监测污染物排放,优化治理策略;以及保护生物多样性,预测物种分布变化等。
3. 应用场景分析 3.
如何理解spring属于低侵入式设计? 在代码中不需要写明具体依赖对象,在运行时进行自动注入,降低了组件的耦合依赖的是接口,而接口的实现类具有拓展性 Spring IOC 实现了什么功能,谈谈你对IOC的理解。 负责创建对象,管理对象(通过依赖注入(DI)装配对象、配置对象)并且管理这些对象的整个生命周期。
功能:
依赖注入(DI): 生命周期管理:Spring
控制反转:将对象的创建权交由外部容器,将Bean加入IOC容器 Spring IOC
IOC容器还负责管理Bean的生命周期。它会根据配置来创建Bean,初始化Bean,以及在不再需要时销毁Bean。
配置集中管理:Spring IOC容器允许将应用的配置集中到一个或多个地方,使得配置的管理更加方便。
Spring提供了哪些实现DI的方式? Spring提供了以下几种实现依赖注入(DI)的方式:
Setter注入:这是最常用的注入方式。Spring IOC容器通过调用Bean的setter方法,将依赖注入到Bean中。
构造器注入:Spring IOC容器通过调用Bean的构造器,并传入所需的依赖,来完成依赖注入。
注解注入:Spring还支持基于注解的依赖注入。例如,可以使用@Autowired注解来自动注入依赖。
自动装配注入:Spring IOC容器可以自动装配Bean的依赖。例如,如果一个Bean需要另一个Bean,Spring IOC容器可以自动找到并注入所需的Bean。
静态工厂注入:通过静态工厂方法返回的实例进行依赖注入。
实例工厂注入:通过实例工厂方法返回的实例进行依赖注入。
DI注入如何实现单例变多例,这个过程中产生的现象都是谁在管理? [在Spring中,Bean默认是单例模式,也就是说,Spring IOC容器在初始化时会创建Bean的一个实例,并在整个应用中复用这个实例。但是,我们可以通过配置将单例模式变为多例模式]
实现单例变多例的方式主要有以下几种:
XML配置:在Bean的XML配置中,可以通过设置scope="prototype"来实现多例模式
例如:
<bean id="xxx" class="全类名" scope="prototype"></bean> 注解:可以使用@Scope("prototype")注解来使对象成为多例模式
例如:
@Component @Scope("prototype") public class SomeClass { // ... } [在这个过程中,所有的现象都是由Spring IOC容器来管理的。当我们将一个Bean配置为多例模式后,每次从Spring IOC容器中获取该Bean时,都会创建一个新的实例。
需要注意的是,多例模式在进行注入时,不能使用@Autowired,否则注入的还是单例模式。实现多例模式需要使用工厂模式例如,可以通过实现BeanFactoryAware接口来获得factory
此外,如果你想在一个请求的生命周期内保持Bean的实例是唯一的,你可以使用@Scope("request")或@Scope("session")。这两种模式分别表示在一次HTTP请求中和在一个会话中,被注解的Bean都是同一个Bean
OOP 和 AOP 的区别是什么? OOP面向对象编程,纵向结构关系,关注类之间的关系.OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。它导致了大量代码的重复,而不利于各个模块的重用。
AOP可以说是OOP(Object Oriented
Programming,面向对象编程)的补充和完善。AOP面向切面编程,横向结构关系,关注类的内容.
剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块.使用AOP,可以在不修改原来代码的基础上添加新功能。
Spring 通过AOP实现了什么功能?这项技术你是如何使用的? 【实现功能】
使用AOP,可以在不修改原来代码的基础上添加新功能。 模块化横切关注点:Spring
AOP将横切关注点(例如日志记录、事务管理、安全性检查等)从主业务逻辑代码中分离出来,以模块化的方式实现对这些关注点的管理和重用
动态代理:Spring AOP使用动态代理技术,在目标对象方法执行时将切面的逻辑织入到目标对象的方法中
项目目录 app/ ├── container/ │ ├── init.sh │ ├── nginx.conf.template ├── src/ ├── .gitlab-ci.yml └── deploy.sh └── Dockerfile └── Makefile container目录是放nginx的配置文件,给nginx镜像使用
.gitlab-ci.yml和Makefile是cicd自动发版,适用于测试环境和生产环境
deploy.sh是使用shell手动发版,适用于开发环境
下面是以上配置文件 init.sh
主要作用是根据env环境变量替换nginx的反向代理地址
#!/bin/bash BACKENDURL=$BACKENDURL export "BACKENDURL"=$BACKENDURL envsubst '$BACKENDURL' < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf && nginx -g 'daemon off;' nginx.conf.template
user root; events { worker_connections 4096; ## Default: 1024 } http { proxy_connect_timeout 300000; #连接握手时间 proxy_send_timeout 300000; # 设置发送超时时间, proxy_read_timeout 300000; # 设置读取超时时间。 client_max_body_size 100M; include /etc/nginx/mime.types; sendfile on; server { listen 80; listen [::]:80; add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Headers X-Requested-With,access-token,Access-Token,Refresh-Token,Accept,Content-Type,User-Agent; add_header Access-Control-Allow-Methods GET,POST,OPTIONS; location / { root /usr/share/nginx/html; index index.
要查看MySQL使用的内存,我们可以通过多种方式来获取相关信息。以下是几种常见的方法,包括使用命令行工具、MySQL的系统变量以及查询information_schema数据库。
1. 使用SHOW STATUS命令 我们可以使用SHOW STATUS命令来查看MySQL服务器状态,其中包括一些与内存使用相关的变量。
SHOW STATUS LIKE 'Innodb_buffer_pool_read%'; SHOW STATUS LIKE 'Innodb_buffer_pool_wait%'; SHOW STATUS LIKE 'Innodb_buffer_pool_pages%'; SHOW STATUS LIKE 'Innodb_log_sequence_number'; SHOW VARIABLES LIKE 'innodb_buffer_pool_size'; Innodb_buffer_pool_read%:与InnoDB缓冲池读取相关的状态。
Innodb_buffer_pool_wait%:显示由于需要等待内存而发生的延迟读取和写入请求的数量。
Innodb_buffer_pool_pages%:与InnoDB缓冲池页面相关的状态。
Innodb_log_sequence_number:显示日志序列号,虽然不是直接关于内存的,但它是InnoDB重做日志的一个重要指标。
innodb_buffer_pool_size:这是一个配置变量,显示InnoDB缓冲池的大小(以字节为单位)。
2. 使用SHOW VARIABLES命令 我们可以使用SHOW VARIABLES命令来查看MySQL服务器的配置变量,其中一些与内存使用有关。
SHOW VARIABLES LIKE 'max_connections'; SHOW VARIABLES LIKE 'query_cache_size'; SHOW VARIABLES LIKE 'innodb_buffer_pool_size'; SHOW VARIABLES LIKE 'innodb_log_buffer_size'; -- 以及其他与内存相关的变量 这些变量为我们提供了关于MySQL如何配置其内存使用的信息。
3. 查询information_schema数据库 虽然information_schema数据库主要包含关于数据库元数据的信息,但它也包含一些与性能相关的表,如PROCESSLIST,我们可以用它来查看当前运行的查询及其使用的资源。然而,它并不直接提供关于MySQL服务器总内存使用的信息。
4. 使用性能监控工具 除了上述的SQL命令外,我们还可以使用如Percona Monitoring and Management (PMM)、MySQL Enterprise Monitor或开源的Prometheus和Grafana等性能监控工具来查看MySQL的内存使用情况。这些工具通常提供更详细、更直观的视图,并允许我们设置警报和通知。
5. 查看系统资源使用情况 最后,我们也可以在操作系统级别查看MySQL进程使用的内存。在Linux上,我们可以使用top、htop或free -m等命令来查看系统资源的使用情况,并通过进程ID找到MySQL进程。在Windows上,我们可以使用任务管理器或resource monitor来查看类似的信息。
快乐的流畅:个人主页 个人专栏:《算法神殿》《数据结构世界》《进击的C++》 远方有一堆篝火,在为久候之人燃烧! 文章目录 引言一、单词搜索二、黄金矿工三、不同路径 |||四、图像渲染五、岛屿数量六、岛屿的最大面积七、被围绕的区域八、太平洋大西洋水流问题九、扫雷游戏总结 引言 在二维网络图中的dfs,反而一般不需要画决策树,因为在二维图像中有时候很直观可以看出决策关系,一般为上下左右搜索。
一、单词搜索 细节:
dfs函数设置返回值bool,以便及时调整路线设置向量数组dx,dy设置bool数组vis,实现剪枝pos设置为函数参数,方便回溯 class Solution { int dx[4] = {1, -1, 0, 0}; int dy[4] = {0, 0, 1, -1}; bool vis[7][7]; int m, n; public: bool dfs(vector<vector<char>>& board, int i, int j, string& word, int pos) { if(pos == word.size()) return true; vis[i][j] = true; for(int k=0; k<4; ++k) { int x = i + dx[k], y = j + dy[k]; if(x >= 0 && y >= 0 && x < m && y < n && !
Redis存储方式介绍 在 Redis 中数据是以键值对的凡事存储的,键(Key)和值(Value)是基本的数据存储单元。以下是对 Redis 键值对的详细讲解:
键(Key): 类型:键是字符串类型,可以包含任何二进制数据。
长度限制:键的最大长度为 512 MB。
命名规范:虽然 Redis 对键的命名没有严格的要求,但为了提高可读性和管理性,通常使用有意义的命名规范。例如: session:abc123
值(Value): 值可以是多种数据类型之一,Redis 提供了丰富的数据结构来存储不同类型的数据:
比如字符串(String)、哈希(Hash)、列表(List)、集合(Set)、有序集合(Sorted Set,ZSet)、位图(Bitmap)、HyperLogLog、地理空间索引(Geospatial)、流(Stream)
这里以字符串类型举例,其他数据类型后面会介绍
基础全局命令介绍 设置和获取键值对(string) 这里操作就是这是一个key1 value1的键值对,key1为键,value1为值
设置好后,再用get命令获取到key1对应的值
获取到value1
检查键是否存在 exists key
因为有key1,所以使用key1可以查询到,返回了1
(这里也可以一次性查询多个key,返回就是有几个查到了,就返回几)
没有key2,查询不到,返回0
查找键 keys [pattern]
返回所有满足样式(pattern)的 key。支持如下统配样式。
h?llo 匹配 hello , hallo 和 hxllo
h*llo 匹配 hllo 和 heeeello
h[ae]llo 匹配 hello 和 hallo 但不匹配 hillo
h[^e]llo 匹配 hallo , hbllo , ... 但不匹配 hello
h[a-b]llo 匹配 hallo 和 hbllo
随着信息技术的快速发展,数据处理和计算的需求日益增大,特别是在实时性要求极高的场景中,传统的云计算模式面临着巨大的挑战。在这样的背景下,边缘计算作为一种新兴的计算模式,正逐渐受到业界的广泛关注。那么,什么是边缘计算?它为何如此重要?本文将对其进行详细的解析。
边缘计算,简而言之,是指在靠近物或数据源头的一侧,采用网络、计算、存储、应用核心能力为一体的开放平台,就近提供最近端服务。它的核心思想是将计算任务和数据存储尽可能地推向网络的边缘,即设备或终端,以减少数据传输的延迟,提高响应速度,并增强数据的安全性和隐私保护。
边缘计算的重要性主要体现在以下几个方面:
一、低延迟
在实时性要求极高的应用场景中,如自动驾驶、智能制造、远程医疗等,延迟的减少至关重要。传统的云计算模式需要将数据传输到远离数据源的云端进行处理,这种长距离的传输往往会导致较大的延迟。而边缘计算则可以将计算任务和数据存储部署在靠近数据源的网络边缘,实现数据的就近处理,从而极大地降低延迟,提高系统的实时响应能力。
二、数据隐私和安全
随着大数据和人工智能的广泛应用,数据隐私和安全问题日益凸显。在传统的云计算模式中,大量数据需要通过网络传输到云端进行处理和存储,这增加了数据泄露和被非法获取的风险。而边缘计算通过将数据处理和存储推向网络边缘,减少了数据在网络中的传输距离和时间,降低了数据泄露的风险,提高了数据的安全性和隐私保护水平。
三、带宽利用率
随着物联网设备的爆炸式增长,网络带宽的需求也在不断增加。传统的云计算模式需要将所有数据都传输到云端进行处理,这不仅会导致网络拥堵,还会增加网络带宽的成本。而边缘计算可以在本地设备或终端上进行部分数据处理和存储,只将必要的结果或关键数据传输到云端,从而有效减轻网络的负担,提高带宽的利用率。
四、支持离线操作
在一些特殊场景中,如偏远地区或网络环境不稳定的区域,云端计算可能无法提供稳定的服务。而边缘计算设备可以在本地进行数据处理和存储,无需依赖云端,因此可以在离线状态下正常工作,保证了服务的连续性和稳定性。
综上所述,边缘计算作为一种新兴的计算模式,具有低延迟、数据隐私和安全、高带宽利用率以及支持离线操作等优势,对于解决实时性要求高、数据隐私敏感、网络带宽有限等场景中的问题具有重要意义。随着技术的不断进步和应用场景的不断拓展,边缘计算将在未来发挥更加重要的作用,推动各行业的数字化转型和智能化升级。
用PHP封装一个强大且通用的CURL方法 支持:get、post、put、delete、patch、options
直接上代码:
/** * @function 强大且通用的cURL请求库 * @param $url string 路径 * @param $method string 请求方式 如:get、post、put、delete、patch、options * @param $payload array|string 荷载 如:['foo' => 'bar', 'upload_file' => new CURLFile(file_path)]或json{"foo":"bar"} * @param $request_header array 请求头 如:['Content-Type' => 'json', 'Set-Cookie' => 'foo'] * @param $time_out int 超时秒数 如:10,(单位:秒) * @return array [bool 请求是否成功, string 错误内容, [int http状态码, array 响应头, string 响应主体内容]]; */ function curl($url, $method = 'GET', $payload = [], $request_header = [], $time_out = 10) { $curl = curl_init(); curl_setopt($curl,CURLOPT_URL, $url); $method = strtoupper($method); if ($method == 'POST') { curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, $payload); } else if ($method == 'PUT') { curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT'); curl_setopt($curl, CURLOPT_POSTFIELDS, $payload); } else if ($method == 'DELETE') { curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE'); curl_setopt($curl, CURLOPT_POSTFIELDS, $payload); } else if ($method == 'PATCH') { curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PATCH'); curl_setopt($curl, CURLOPT_POSTFIELDS, $payload); } else if ($method == 'OPTIONS') { curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'OPTIONS'); curl_setopt($curl, CURLOPT_POSTFIELDS, $payload); } else if($method == 'HEAD') { curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'HEAD'); } else { curl_setopt($curl, CURLOPT_HTTPGET, true); } if ((parse_url($url)['scheme'] ?
背景 为了go项目能够尽可能复用代码,把一些公用的工具类,公用的方法等放到共用包里统一管理。把共用包放到gitlab的私有仓库中。
遇到的问题 通过https方式,执行go get报了错误。
通过ssh方式,执行go get报了错误。
修改配置,用ssh请求代替http请求:
git config --global url."git@gitlab.com:groupName/projectName.git".insteadOf "https://gitlab.com/groupName/projectName.git"` 配置完成之后,使用go get拉取私有仓库代码。
go get -u -v gitlab.com/groupName/projectName 依然不行,还是报了错。
设置这两个环境变量:
setx GOPRIVATE git.dreame.tech setx GONOSUMDB git.dreame.tech 设置了这两个环境变量,依然不行,还是会报错。
这个问题在于公用包go mod中的path路径不对。
公用包的项目不要直接直接go mod init进行初始化。如果需要让其他项目引用。需要通过如下指令初始化。
go mod init gitlab.com/groupName/projectName 因为上面修改配置,用ssh请求代替http请求,导致push代码不能成功,报了如下的错误:
这个错误的原因,看了一下,是因为没有ssh协议的权限。接下来,再来搞这个事情。
添加ssh key。
SSH 秘钥默认储存在账户的主目录下的 ~/.ssh 目录。
到该目录下查找秘钥。没有找到rsa.pub文件。这个文件中存放的是公钥信息。
所以,需要生成密钥信息。打开 Git Bash工具。执行这个命令,连续三次按Enter健。这个应该是为了给这个rsa.pub文件设置密码的。
ssh-keygen -t rsa id_rsa.pub就是公钥。
登录gitlab添加sshkey。
总结 第一步:
创建一个公用包的项目,比如,core。这里有个点需要注意,不能直接用go mod init进行初始化,否则,引用该包会报路径错误的问题。需要通过这个命令进行初始化(init后面的内容实是ssh链接去掉git@)。执行完之后,push到gitlab上。
go mod init gitlab.com/groupName/projectName 公用包创建的流程到此就完成了。接下来就是引用包需要做些一些配置。
第二步:
修改配置,用ssh请求代替http请求:
git config --global url.