参考一下
1、信号层(Signal Layers),有16个信号层,TopLayer BottomLayer MidLayer1-14。 2、内部电源/接地层(Internal Planes),有4个电源/接地层Planel1-4。 3、机械层(Mechanical Layers),有四个机械层。 4、钻孔位置层(Drill Layers),主要用于绘制钻孔图及钻孔的位置,共包括Drill Guide 和Drill drawing两层。 5、助焊层(Solder Mask),有TopSolderMask和BottomSolderMask两层,手工上锡。 6、锡膏防护层(Paste Mask)有TopPaste和BottomPaster两层。
7、丝印层(Silkscreen),有TopOverLayer和BottomOverLayer两层,主要用于绘制元件的外形轮廓。 8、其它工作层面(Other): KeepOutLayer:禁止布线层,用于绘制印制板外边界及定位孔等镂空部分。 MultiLayer:多层 Connect:连接层 DRCError:DRC错误层 VisibleGrid:可视栅格层 Pad Holes:焊盘层。
--------------
======
top layer - 顶层
bottom layer - 底层
mechanical,机械层
keepout layer禁止布线层
top overlay顶层丝印层
bottom overlay底层丝印层
top paste顶层助焊层
bottom paste底层助焊层
top solder顶层阻焊层
bottom solder底层阻焊层
drill guide 过孔引导层
drill drawing 过孔钻孔层
multilayer 多层
①顶层和底层:top-layer 和 bottom layer 这个不用多说了,就是我们画板子的正反面呗。。。
②机械层和禁止布线层(mechanical 和 keep-out layer) 这两个关乎板子的外形,。
1.1 保证顺序性的意义 消息队列中的若干消息如果是对同一个数据进行操作,这些操作具有前后的关系,必须要按前后的顺序执行,否则就会造成数据异常。
举例:
比如通过mysql binlog进行两个数据库的数据同步,由于对数据库的数据操作是具有顺序性的,如果操作顺序搞反,就会造成不可估量的错误。比如数据库对一条数据依次进行了 插入->更新->删除操作,这个顺序必须是这样,如果在同步过程中,消息的顺序变成了删除->插入->更新,那么原本应该被删除的数据,就没有被删除,造成数据的不一致问题。
1.2 出现顺序错乱的场景 我们还是以RabbitMQ为例,后续会陆续更新更多的MQ的解决方案。
1.2.1 错乱场景一 ①一个queue,有多个consumer去消费,这样就会造成顺序的错误,consumer从MQ里面读取数据是有序的,但是每个consumer的执行时间是不固定的,无法保证先读到消息的consumer一定先完成操作,这样就会出现消息并没有按照顺序执行,造成数据顺序错误。
1.2.2 错乱场景二 一个queue对应一个consumer,但是consumer里面进行了多线程消费,这样也会造成消息消费顺序错误。
1.3 保证消息的消费顺序 1.3.1 解决方案一 拆分成多个queue,每个queue一个consumer,就是多一些queue而已,确实是麻烦点;这样也会造成吞吐量下降,可以在消费者内部采用多线程的方式取消费。
1.3.2 解决方案二 或者就一个queue但是对应一个consumer,然后这个consumer内部用内存队列做排队,然后分发给底层不同的worker来处理
原始蛋白序列长这个样子:
写脚本的具体思路:
1.创建转录本ID和序列的字典(键值对)
2.提取每个转录本的序列长度,形成三列,第一列是转录本ID,第二列是转录本长度,第三列是gene ID
3.这一步准备对上一步生成的文件按照基因ID和序列长度进行排序
4.创建新的字典(key是gene id,value是排序后的转录本ID),然后print(list_values),第一列就是最长转录本ID
5.linux系统下利用seqtk subseq工具提取最长转录本序列(命令如下:seqtk subseq test_all_pep.fas longest_pep_id.txt > longest_pep.fas),得到最长转录本序列
注意:在第一步创建字典过程中,要让key变得美观一点,将>后面的header修改为>Ljchlorog3v0000020.1这种样子,即转录本后面的注释全部删掉(从第一个空格往后全部删除),利用正则表达式name=re.sub(" .*$","",nameS)
输入文件为test_all_pep.fas 其中第2步的结果文件名为gene_id_len.txt 第3步的结果文件名为gene_id_len_sorted.txt 第4步的结果文件名为longest_pep_id.txt
输入文件,输出文件,脚本在下方网盘链接
#!/usr/bin/env python # -*- coding=utf-8 -*- ''' 提取序列文件中最长的转录本ID 需要修改######位置的参数 以及 open的目录 ''' import sys import re Fasta=open("D:/python/Code/jupyter-notebook/test_all_pep.fas","r") Sequence={} ## 1.创建ID和序列的字典 for line in Fasta.readlines(): content=line.strip() if content.startswith(">"): nameS=content[1:] name=re.sub(" .*$","",nameS) ######修改一下序列的header Sequence[name]='' else: Sequence[name]+=content Fasta.close() #print(Sequence.keys()) ## 2.提取每个转录本的序列长度,形成三列 Out=open("D:/python/Code/jupyter-notebook/gene_id_len.txt","w") for i in Sequence.keys(): #print(i+"\t"+str(len(Sequence[i]))+"\t"+i.split(".")[0]+"\n") Out.write(i+"\t"+str(len(Sequence[i]))+"\t"+i.split(".")[0]+"\n") #第一列是转录本ID,第二列是转录本长度,第三列是gene ID Out.
是Java自己的注解:
@PostConstruct该注解被用来修饰一个非静态的void()方法。
被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。PostConstruct在构造函数之后执行,init()方法之前执行。
通常我们会是在Spring框架中使用到@PostConstruct注解 该注解的方法在整个Bean初始化中的执行顺序:
Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)
@Component public class Test { @PostConstruct public void init(){ System.out.println("Hello!!"); } } 站在巨人的肩膀上:
@PostConstruct注解,你该好好看看 - 知乎 (zhihu.com)(其他大佬遇到的一些情况)
随着分布式微服务的兴起,越来越多的公司在开发web项目的时候选择前后端分离的模式开发,前后端分开部署,使得分工更加明确,彻底解放了前端。
我们知道,http请求都是无状态,现在比较流行的都是jwt的形式处理无状态的请求,在请求头上带上认证参数(token等),前后端分离有好处,也有坏处,第一次开发前后端分离项目的人,肯定会遇到前端请求跨域的问题,这个怎么处理呢?在说处理方案前,有必要说明一下为什么会跨域和什么是跨域?
一、为什么会跨域? 出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的 javascript 脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)
二、什么是跨域? 当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域
当前页面url(即浏览器地址)被请求页面url(即后端接口地址)是否跨域原因https://www.site.com/https://www.site.com/index.html否同源(协议、域名、端口号相同)https://www.site.com/http://www.site.com/index.html是协议不同(https/http)https://www.site.com/https://www.baidu.com/是主域名不同(site/baidu)https://www.site.com/https://layui.site.com/是子域名不同(www/layui)https://www.site.com:8080/https://www.site.com:8081/是端口不同(8080/8081) 三、实现跨域访问 两种方面来解决
前端解决(不是根本解决方案,打包后还是得由后端解决)后端解决代理服务器 3.1 前端代理访问 在vue的开发环境中跨域,通过代理的方式来实现,类似于nginx。
比如以下范例,访问 csdn 的测试接口api。
// config/index.js module.exports = { dev: { // Paths assetsSubDirectory: 'static', assetsPublicPath: '/', proxyTable: { '/api': { // 真实接口域名 target: 'https://www.csdn.net', // 开启代理 changeOrigin: true, pathRewrite: { // 重写请求地址,即将字符串^/api替换成你想要的字符串,拼接到target '^/api': '/api' } }, '/v1': { target: 'https://suggest-follow-api-ms.juejin.im', changeOrigin: true, pathRewrite: { '^/v1': '/v1' } } }, }, } 代码中的请求方式
method: { ajaxFun() { var url = '/api/articles?
准备一个纯净的ubantu系统
1、先更新一下安装列表
sudo apt-get update
2、安装docker.io
sudo apt install docker.io
查看是否安装成功
docker -v
3、查看是否安装pip
pip -V
检测到未安装,提示是否安装,按y下载
再次输入pip -V查看是否安装成功
4、安装docker-compose
pip install docker-compose
查看是否安装成功
docker-compose -v
5、下载靶场文件
git clone https://github.com/vulhub/vulhub.git
接下来就针对某个漏洞进行docker启用并复现漏洞
访问:Vulhub - Docker-Compose file for vulnerability environment
比如我们现在要复现Apache HTTPD未知后缀名漏洞,找到进入路径
按照以上路径,从ubantu进入
cd apache_parsing_vulnerability
启动docker(会自动构造漏洞环境)
docker-compose up -d
查看靶机ip
ifconfig
打开物理机浏览器访问该ip,打开靶机环境
查看教程,需要上传一个文件,文件名为xxx.php.jpeg,上传以后,该文件被当成php文件执行,而不是作为jpeg图片
物理机新建一个txt文档,输入<?php phpinfo();?> 保存名为1.php.jpeg
打开刚才漏洞环境,上传该文件
文件上传成功,复制红框内的文件路径,和IP拼接为新的url http://192.168.98.30/uploadfiles/1.php.jpeg
访问 http://192.168.98.30/uploadfiles/1.php.jpeg ,出现如下界面,说明1.php.jpeg文件被执行了,说明该系统存在后缀名解析漏洞
其他漏洞复现都可以访问Vulhub - Docker-Compose file for vulnerability environment,每个漏洞都有详细复现过程,祝大家靶场通关,技术提升。
一、安装openvino 巨详细!使用OpenCV和OpenVINO轻松创建深度学习应用_我爱计算机视觉-CSDN博客
下载网址:Download Intel® Distribution of OpenVINO™ Toolkit
版本选择:LINUX offline 2021.04 二、过程报错 ./demo_squeezenet_download_convert_run.sh 报错:
ERROR: Cannot uninstall 'PyYAML'. It is a distutils installed project and thus we cannot accurately determine which files belong to it which would lead to only a partial uninstall.
输入
pip install --ignore-installed pyyaml 报错
ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
STM32MP157开发板使用手册更新啦最新版本为1.2版本。后续资料会不断更新,不断完善,帮助大家快速入门,大大提升研发速度,大家在研发过程中遇到什么问题也可以在评论区留言哦~
更新重点:
本次更新包括配套网盘资料和配套开发文档
1 对linux内核移植章节做了更新,并更新了对应的内核源码。
* 适配了新七寸LVDS屏幕参数
* 对每个屏幕的触摸设备节点进行调整
* 将ov5640摄像头驱动、每个屏幕的触摸驱动加载进了内核
2 对buildroot构建文件系统章节做了更新,并更新了对应的文件系统
* 完善了QT编译和测试章节内容
*对ov5640摄像头的测试命令进行了适配
3 为了解决ext4文件系统镜像的初始存储问题,增加15.9 小节文件系统分区扩容工具的移植和使用章节
4 增加了M4核心freertos实时系统开发部分,具体的章节内容如下:
第36章 认识freertos
第37章 Freertos的任务基础知识
第38章 任务管理实验
第39章 消息队列实验
第40章 二值信号量实验
第41章 计数信号量实验
第42章 事件实验
第43章 软件定时器实验
在这些章节中,我们通过实验的方式,对freertos的各种功能的运用进行初步的了解,在后续的学习过程中,我们也会在目前已有的基础上进行扩展。
STM32MP157开发板手册更新记录
第一部分硬件及资料介绍
第零章 开发板使用前必读
必须注意的问题
01硬件配件检查
第一章 iTOP-STM32MP157开发板简介
1.1核心板介绍
1.2 底板介绍
1.3 底板硬件资源接口
1.4 扩展口原理图和PCB管脚对应方式
第二章 开发板组装
2.1 电源的连接
2.2 控制台(console)串口
2.3 屏幕的连接
第三章 外设功能验证
3.1 用户LED测试
3.2 蜂鸣器测试
3.3 ADC电位器测试
上一篇中我们讲了八皇后递归的思路,但是代码实在是不堪入目,因为从零到七要试探上千万次,简直无法忍受,而我们也知道八皇后的排列方式就是8!的全排列问题,由此可在上一篇的基础上进行代码优化进一步减少运行次数(但还不是最简方法),由原来的需要判断上千万次减少为40320次虽然还是很多,但对于计算机来说还是可以接受的。
代码以及说明如下: import java.util.ArrayList; import java.util.List; public class QueenDemo { public static void main(String[] args) { int[] arr=new int[9];//多出一个位置存结果 List<Integer> list= new ArrayList<>();//list用来存储已有的值,防止重复,用栈的话也可以 getCount(arr,list,8); System.out.println(arr[8]); } //全排列问题的解决方案8皇后运行40320次 public static void getCount(int[] arr,List<Integer> list,int max){ for (int i = 0; i < arr.length-1; i++) { //如果list中包含之前的值就跳过,减少判断次数 if(list.contains(i)){ continue; } arr[max-1]=i; //没有就添加进去 list.add(i); //当数组调整好就去验证 if(max==1){ if(judge(arr)){ arr[arr.length-1]++;//可以把if条件取消验证全排列次数 } //arr[arr.length-1]++; } else { getCount(arr,list,--max); //这里值得注意,如果退出最后一层循环列表中要删除两次最后一位,其余循环只删除一次 // 它喵的就在这里我debug了一个半点,固定删除一次或删除两次都有问题,只有这样才行,至于为什么,debug一下你就知道,真他喵的坑爹 if(max==1){ list.remove(list.size()-1); list.remove(list.size()-1); } else { list.
众所周知word/WPS中的邮件合并功能可以根据word模板从excel表格中读取数据,进而生成不同的文件,但是邮件合并也有其缺陷,那就是每次合并数据都需操作插入合并域,如果经常需要根据数据生成固定模板word文件,那么就显得很麻烦
利用程序固定数据替换模式,需要生成文件时可以一键操作就极为方便
工具:python解释器,xlrd包(Excel数据读取),docx-mailmerge包(邮件合并包)
docx-mailmerge仅支持docx格式文件
2种文件生成方式:合并到同一新文件,合并到不同新文件
首先制作邮件合并模板 域名可以使用中文
最终完成的word模板,wps操作步骤类似
excel数据 导入python模块 import os.path import xlrd from mailmerge import MailMerge python代码,合并到同一新文件 def merge_1(): """ word邮件合并到同一新文件,word、wps模板均可 根据Excel每行数据生成单个同一模板word文件 """ docx = r'E:\测试\证明-模板.docx' xlsx = r'E:\测试\证明数据.xlsx' filepath = os.path.dirname(docx) wb = xlrd.open_workbook(xlsx) ws = wb.sheet_by_index(0) nrow = ws.nrows list_temp = [] # 空列表 for key in range(1, nrow): dict_temp = {} # 空字典 dict_temp['name'] = str(ws.cell_value(key, 1)) dict_temp['position'] = str(ws.cell_value(key, 2)) list_temp.append(dict_temp) with MailMerge(docx) as doc: doc.
复试所涉及的科目 C语言1-1011-2122、指针变量的本质?23、√ 堆和栈的区别?24-2526、√ 数组和链表的区别27、什么是预编译,何时需要预编译?28、√ 数组和指针的区别29、√ 结构体和数组的区别30、结构体和共用体 单片机1、√ 简述累加器的ACC的作用2、√简述串行数据传送的特点3、51系列单片机具有几个中断源,分别是如何定义的?其中哪些中断源可以被定义成高优先级中断,如何定义?4、单片机的复位电路有几种形式?复位后PC/IE/SP内容?5、√ 中断?中断响应和中断返回?6、√ 中断返回和子程序返回的异同?7、√ 什么是单片机、什么是嵌入式?两者有何区别和联系? 总结 笔者从21年2月份开始全面备战考研,断掉了之前的文章更新。现在已经成功通过初试,开始备战复试,现在在这里进行一个总结,每个科目大概准备20左右个问题,打√为重点。 C语言 1-10 1、预编译处理不是C语言的一部分,不占运行时间,不要加分号。C语言编译的程序称为源程序,它以ASCII数值存放在文本文件中。
预编译处理:旨在进行编译之前,系统自动引用预处理程序 对源程序 中的预处理
ASCII码特殊值:
"0"-48D-30H; "a"-97D-61H; "A"-65D-41H; "0-9"--"30-39"(H); "a-z"--"61-7A"(H); "A-Z"--"41-5A"(H). 2、C语言程序中main函数有且只有一个,是程序运行的起点。
3、函数中不可以再定义函数。
4、算法:可以没有输入,但是一定要有输出。
5、break可用于循环结构和switch语句。
6、bit是位——是指0/1;byte是字节;一字节=八个位。
8、每个C语言程序(.c)写完之后,都是先编译(.obj),再链接(.exe),最后运行。
9、C语言只有八、十、十六进制,没有二进制。但是运行的时候,所有的进制都要转换成二进制来进行处理。
10、long int x;表示x是长整型;unsigned int x;表示x是无符号整型。
11-21 11、int x=i++;是先赋值后加1;int x=++i;是先加1后赋值。
12、在没有舍去数据时,<<左移一位表示乘以2;>>右移一位表示除以2。
13、使用printf和scanf函数时,要在最前面加上#include"stdio.h"
14、C语言中共有&&(双与);||(双或);!(非)三种逻辑运算符号。
15、C语言中使用1表示逻辑真的,用0表示逻辑假的。
16、条件表达式:表达式1?表达式2:表达式3;表示即1为真时执行2,为假时执行3。
17、程序结构是三种:顺序结构、选择结构与循环结构。
18、switch-case语句,根据选择的值执行相应的case,若case后面没有break,则后面的语句都要执行。有break,跳出当前case,结束当前循环。
19、continue和break的区别:break是跳出循环,continue是继续循环。
20、常见的死循环:for( ; ; ) 、while(1)
21、函数的参数可以是常量,变量,表达式,甚至是函数调用。
22、指针变量的本质? 是用来放地址的,而一般的变量是放数值的。
23、√ 堆和栈的区别? 定义上:
栈区(stack)——由编译器自动分配释放,存放函数的参数值、局部变量的值等其操作方式类似于数据结构中的栈;
堆区(heap)——一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。
性质上:
在栈上创建——在执行函数时,函数内局部变量的储存单元都可以在栈上创建,函数执行结束时,这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集。
从堆上分配——亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由程序员决定,使用非常灵活,但问题也最多。
24-25 24、程序的局部变量存在于(堆栈)中,全局变量存在于(静态区)中,动态申请存在于(堆)中。
25、队列与栈的区别:队列先进先出,栈后进先出。
Hadoop集群动态扩缩容 1 项目需求 随着公司业务的增长,数据量越来越大,原有DataNode节点的容量已经不能满足数据存储的需求,需要在原有集群基础上动态添加新的数据节点,也就是俗称的动态扩容。如果在Hadoop集群运行过程中,某些节点变得反常,例如故障率过高或者性能过低,可能就需要停止这些节点上的Hadoop服务,并从Hadoop集群中移除,也就是俗称的动态缩容。通常情况下,节点需要同时运行DataNode和NodeManager守护进程,所以两者一般同时新增或者移除。
2 动态扩容原理 增加一个新节点非常简单:首先配置hdfs-site.xml文件指向NameNode,然后配置yarn-site.xml文件指向ResourceManager,最后启动DataNode和NodeManager守护进程即可。
然而随便允许一台机器以DataNode的身份连接到NameNode是非常不安全的,因为该机器很可能会访问未授权的数据。此外,这台机器可能并非真正的DataNode,不在集群的控制之内,随时可能停止从而导致潜在的数据丢失。另外由于错误配置的可能性,即使这台机器都在本机房的防火墙之内,这种做法的风险也比较高。因此所有工作集群上的DataNode(或者NodeManager)都应该被明确管理。
我们将允许连接到NameNode的所有DataNode都放在一个文件中,文件名称由dfs.hosts属性指定,该文件的每一行对应一个DataNode的网络地址。类似的,可能连接到ResourceManager的各个NodeManager也是在一个文件中指定,该文件的名称由yarn.resourcemanager.nodes.include-path属性指定。
在通常情况下,由于集群中的节点同时运行DataNode和NodeManager守护进程,dfs.hosts和yarn.resourcemanager.nodes.include-path会同时指向一个文件,即取名为include文件。include文件不同于slaves文件,前者提供NameNode和ResourceManager使用,用于决定可以连接到哪些工作节点。Hadoop控制脚本使用slaves文件执行面向整个集群范围的操作,比如启停Hadoop集群等,而Hadoop守护进程从来不会使用slaves文件。
3 动态缩容原理 HDFS集群能够容忍DataNode故障,这并不意味着我们可以随意终止DataNode。HDFS集群默认配置为3个副本,如果同时关闭不同机架上的3个DataNode,则数据丢失的概率非常高。正确的操作方法是,我们将准备移除的DataNode告知NameNode,那么HDFS集群会在DataNode停机之前,将数据块复制到其他DataNode,从而实现数据容错。
有了NodeManager的支持,YARN集群对故障的容忍度更高。如果关闭一个正在运行MapReduce作业的NodeManager,ApplicationMaster会检测到故障,并在其他NodeManager节点上重新调度失败的任务。
需要移除的节点是由exclude文件控制。对于HDFS集群来说,exclude文件路径是由dfs.hosts.exclude属性设置。对于YARN集群来说,exclude文件路径是由yarn.resourcemanager.nodes.exclude-path属性设置。通常情况下,准备移除的节点同时运行着DataNode和Nodemanager守护进程,这两个属性指向同一个文件。
4 原Hadoop集群配置与启动 在Hadoop集群进行动态扩缩容之前,首先需要修改原有集群的配置文件,具体操作步骤如下所示。
1.配置include文件路径 在NameNode节点(hadoop1)上,修改hdfs-site.xml配置文件添加dfs.hosts属性,具体操作如下所示。
[hadoop@hadoop1 hadoop]$ vi hdfs-site.xml
<property>
<name>dfs.hosts</name>
<value>/home/hadoop/app/hadoop/etc/hadoop/include</value>
</property>
在ResourceManager节点(hadoop1)上,修改yarn-site.xml配置文件添加
yarn.resourcemanager.nodes.include-path属性,具体操作如下所示。
[hadoop@hadoop1 hadoop]$ vi yarn-site.xml
<property>
<name>yarn.resourcemanager.nodes.include-path</name>
<value>/home/hadoop/app/hadoop/etc/hadoop/include</value>
</property>
2.创建include文件 在NameNode和ResourceManager节点(hadoop1)上,创建include文件,并将集群节点的hostname信息添加到include文件中,具体操作如下所示。
[hadoop@hadoop1 hadoop]$ vi include
hadoop1
hadoop2
hadoop3
3.配置exclude文件路径 在NameNode(hadoop1)节点上,修改hdfs-site.xml配置文件添加dfs.hosts.exclude属性,具体配置如下所示。
[hadoop@hadoop1 hadoop]$ vi hdfs-site.xml
<property>
<name>dfs.hosts.exclude</name>
<value>/home/hadoop/app/hadoop/etc/hadoop/exclude</value>
</property>
在ResourceManager(hadoop1)节点上,修改yarn-site.xml配置文件添加yarn.resourcemanager.nodes.exclude-path属性,具体配置如下所示。
[hadoop@hadoop1 hadoop]$ vi yarn-site.xml
<property>
<name>yarn.resourcemanager.nodes.exclude-path</name>
<value>/home/hadoop/app/hadoop/etc/hadoop/exclude</value>
</property>
4.创建exclude文件 在NameNode节点和ResourceManager节点(hadoop1)上,创建一个空的exclude文件即可,具体配置如下所示。
[hadoop@hadoop1 hadoop]$ touch exclude
第十四章:二叉搜索树 1.二叉搜索树的概念 二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:
若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
它的左右子树也分别为二叉搜索树
2.二叉搜索树的实现 #include<iostream> using namespace std; template<class K> struct BSTNode { BSTNode(const K& key = K()) :_left(nullptr) ,_right(nullptr) ,_key(key) {} BSTNode<K>* _left; BSTNode<K>* _right; K _key; }; template<class K> class BSTree { typedef BSTNode<K> Node; public: BSTree() :_root(nullptr) {} BSTree(const BSTree<K>& t) { _root = _Copy(t._root); } BSTree<K>& operator=(const BSTree<K>& t) { swap(_root, t._root); return *this; } ~BSTree() { _Destory(_root); } //递归插入 bool InsertR(const K& key) { return _InsertR(_root, key); } //递归查找 Node* FindR(const K& key) { return _FindR(_root, key); } //递归删除 bool EraseR(const K& key) { return _EraseR(_root, key); } bool Insert(const K& key) { if (_root == nullptr) { _root = new Node(key); return true; } Node* pre_cur = nullptr; Node* cur = _root; while (cur) { if (cur->_key < key) { pre_cur = cur; cur = cur->_right; } else if (cur->_key > key) { pre_cur = cur; cur = cur->_left; } else { return false; } } cur = new Node(key); if (pre_cur->_key < key) { pre_cur->_right = cur; } else { pre_cur->_left = cur; } return true; } //查找 Node* Find(const K& key) { Node* cur = _root; while (cur) { if (cur->_key < key) { cur = cur->_right; } else if (cur->_key > key) { cur = cur->_left; } else { return cur; } } return nullptr; } //删除 bool Erase(const K& key) { //空二叉树 if (_root == nullptr) { return false; } //查找 Node* pre_cur = nullptr; Node* cur = _root; while (cur!
Centos7 安装nginx-1.9.9教程 第一步:安装所需环境 Nginx 是 C语言 开发,建议在 Linux 上运行,当然,也可以安装 Windows 版本,本篇则使用 CentOS 7 作为安装环境。
rpm -qa|grep gcc 1. gcc 安装 安装 nginx 需要先将官网下载的源码进行编译,编译依赖 gcc 环境,如果没有 gcc 环境,则需要安装:
yum install gcc-c++ 2. PCRE pcre-devel 安装 PCRE(Perl Compatible Regular Expressions) 是一个Perl库,包括 perl 兼容的正则表达式库。nginx 的 http 模块使用 pcre 来解析正则表达式,所以需要在 linux 上安装 pcre 库,pcre-devel 是使用 pcre 开发的一个二次开发库。nginx也需要此库。命令:
yum install -y pcre pcre-devel 3. zlib 安装 zlib 库提供了很多种压缩和解压缩的方式, nginx 使用 zlib 对 http 包的内容进行 gzip ,所以需要在 Centos 上安装 zlib 库。
VS2017开发动态链接库并调试 一、创建动态链接库工程 启动VS2017,选择菜单栏文件 > 新建 > 项目 > 已安装 > Visual C++ > Windows桌面 > 具有导出项的(DLL)动态链接库,设置好工程名称和路径,单击确定完成工程创建。
动态链接库工程创建后,会生成一个模板工程,如图所示。在模板工程中给出了怎样导出类、变量和函数的例子。
在mydll.h文件中已经定义好了动态链接库的导出宏。
// 下列 ifdef 块是创建使从 DLL 导出更简单的 // 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 MYDLL_EXPORTS // 符号编译的。在使用此 DLL 的 // 任何项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将 // MYDLL_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的 // 符号视为是被导出的。 #ifdef MYDLL_EXPORTS #define MYDLL_API __declspec(dllexport) #else #define MYDLL_API __declspec(dllimport) #endif 为了便于多文件导出目标函数,先对模板工程进行简单修改,在解决方案窗口中,右键mydll工程 > 添加 > 新建项 > 已安装 > Visual C++ > 头文件,将文件名修改为export.h,单击添加完成。
在export.h文件中添加如下代码。
#pragma once #ifndef MYDLL_EXPORT_H_ #define MYDLL_EXPORT_H_ // 下列 ifdef 块是创建使从 DLL 导出更简单的 // 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 MYDLL_EXPORTS // 符号编译的。在使用此 DLL 的 // 任何项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将 // MYDLL_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的 // 符号视为是被导出的。 #ifdef MYDLL_EXPORTS #define MYDLL_API __declspec(dllexport) #else #define MYDLL_API __declspec(dllimport) #endif #endif // !
混合开发线上构建之flutter包大小优化 前景打包flutterflutter引擎包的来源缩减fluter framework大小总结 前景 因为项目要使用jenkins线上构建,所以整个项目的资源都要上传到git或者svn仓库里面,而某些仓库有大小限制,超过一定大小,就会不让上传,同时因为一个flutter的release的framework占据有几百M,你代码上传、拉取都会变得很慢,也影响构建的速度。
针对这一现象,就要考虑如何去做进一步优化。
打包flutter 线上构建使用flutter自带的命令flutter build ios --no-codesign --release进行打包,通过这个命令后,会在flutter宿主中的build文件内产生一个iOS的文件夹,就是打包出来的成果物,在Release-iphoneos文件夹下就是打包出来的framework。
这里因为是使用flutter module,还有flutter plugin开发,而且混合开发有引入的内网的三方库,导致如果直接按照官方打包flutter build ios-framework会拉不下内网的三分库。
flutter引擎包的来源 flutter build ios这个命令在源码中,追踪Framework来源比较复杂,涉及到Xcode命令,里面逻辑比较复杂,只是全局搜索到了一个xcode脚本内,包含了相关代码,如果有研究兴趣的,可以私信我,或者等候我之后分享的文章,里面可以真机调试源码,直接打断点。
所以我们使用另外一个命令flutter build ios-framework来追踪源码,猜测大致来源。
这是终端命令行的输出内容,然后我们比对源码。
从这里就很明显的看出,当输入参数不含cocoapods时,会直接copyFlutter的framework包
,从截图的终端命令里面也能看出来,是├─Copying Flutter.xcframework...,追踪源码,flutter的framework包存放在本地的flutter版本内,本地flutter位置/bin/cache/artifacts/engine
参数cocoapods,是指不会直接打出flutter的framework,而是打出一个podspec文件,在我们项目中去引用这个podspec。
这里也包含了android相关的包
查看当前flutter位置,可以使用终端命令which flutter
flutter命令的源码在当前flutter环境所在位置/packages/flutter_tools
缩减fluter framework大小 上面步骤已经成功打出了flutter的引擎包和相关的代码,但是一个flutter的framework很大,2.0.1的有440M。我们线上的就是直接把这个framework包拿过去用了,因为线上构建,所以这个440M的包也上传到项目内,这里就是优化的点,一个项目可能大就大了,但是项目很多的时候,每个仓库里面都占了很大内存,其次,一个flutter版本对应一个稳定的flutter的framework,没必要上传上去。
release对应的flutter包很大,debug和profile模式对应的要小很多
首先想到的一种方案就是,我们可以把这个flutter的framework提取出来,使用podspec去引用,这样线上仓库不会占用很大面积,得到包大小优化,但是这样,只是线上仓库得到优化,每次拉取三方库后,依旧会让整个项目的大小很大,所以有了进一步优化。
当我们项目打完包之后,发现大小并没有几百M,通过查看ipa内部,发现flutter只有14.7M
通过查资料发现,Xcode对framework在打包发布时有一定优化处理,剥离bitcode,去除了很多无用的代码和资源,导致包的大小又缩减一层,直接编译,虽然禁用了bitcode,但是没有做剥离操作,这里就是我们最终优化的方案。
注意:
默认的framework是enable bitcode,这样会导致项目编译失败;
我们使用的flutter的framework会设置bitcode为NO,只是禁用,但是没有剥离bitcode相关的代码和资源。
使用Xcode自带的命令xcrun bitcode_strip -r Flutter.framework/Flutter -o Flutter.framework/Flutter,我们对440M的可执行文件进行操作,大小变成了14.4M和最后的14.7M还是有点差距
后来经过测试,我们直接把14.4M的flutter的framework拖进项目中,然后去打包出一个ipa,最后发现包的大小依然是14.7M,证明我们的操作没有错误,应该是Xcode对framework做了签名之类的操作,导致大小增加了一点。
测试了一下,去除bitcode后,直接拖进项目中,不影响flutter项目的运行与使用
同理,我们可以对打包出来的App.framework也可以进行剥离bitcode操作,减小framework包的大小。
App.framework这是我们编写的flutter的代码打出来的包
总结 最后优化步骤为:
提取flutter的framework和App.framework脚本命令剥离bitcode,使用xcrun bitcode_strip -r Flutter.framework/Flutter -o Flutter.framework/Flutter放在自己的受控库中,使用podspec拉取framework,或者在线上构建时就直接多做一步,因为大小缩减了很多,可以不用上传受控库 注意事项:这里仅限flutter打包成framework后,再引入到原生项目中,这样操作可以减小仓库大小,平时flutter开发时,依然使用完整的flutter的framework,而且每次pub get后,还会从sdk环境copy过去
我用的是centos7系统
安装超级简单,一条命令就解决了
yum install -y qt5-default qtcreator 可以看到在安装
[root@localhost 文档]# yum install -y qt5-default qtcreator 已加载插件:fastestmirror, langpacks Loading mirror speeds from cached hostfile * base: mirrors.163.com * epel: ftp.riken.jp * extras: mirrors.aliyun.com * updates: ftp.riken.jp 没有可用软件包 qt5-default。 正在解决依赖关系 --> 正在检查事务 ---> 软件包 qt-creator.x86_64.0.4.1.0-5.el7 将被 安装 --> 正在处理依赖关系 qt-creator-data = 4.1.0-5.el7,它被软件包 qt-creator-4.1.0-5.el7.x86_64 需要 --> 正在处理依赖关系 gcc-c++,它被软件包 qt-creator-4.1.0-5.el7.x86_64 需要 --> 正在处理依赖关系 libQt5Designer.so.5(Qt_5)(64bit),它被软件包 qt-creator-4.1.0-5.el7.x86_64 需要 --> 正在处理依赖关系 libQt5DesignerComponents.so.5(Qt_5_PRIVATE_API)(64bit),它被软件包 qt-creator-4.1.0-5.el7.x86_64 需要... 等待安装完成,可以看到qt creator已经安装好了
数据集介绍 UCSD是一个行人异常检测数据集(官网:http://www.svcl.ucsd.edu/projects/anomaly/dataset.htm)。通过安装在高程处的固定摄像头获取,可俯瞰人行道。
数据被拆分为 2 个子集,每个子集对应于不同的场景。从每个场景录制的视频片段被分成大约200帧的各种剪辑。
Peds1:一群人走向和远离相机的片段,以及一定程度的透视失真。包含 34 个train视频示例和 36 个test视频示例。
Peds2:行人平行于摄像机平面移动的场景。包含 16 个train视频示例和 12 个test视频示例。
对于每个剪辑,每帧都包含一个二进制标志,指示该帧是否存在异常。其中train集全部为正常帧,test有异常帧,标签数据在.m (matlab) 文件中,为方便读取,我将其以TXT格式存储在label_txt文件夹中。
此外,还为 Peds1 的 10 个剪辑和 Peds2 的 12 个剪辑提供了手动生成的像素级二进制掩码,用于标识包含异常的区域。这旨在能够评估与算法定位异常的能力相关的性能。在文件夹中用’_gt’ 文件表示。
异常事件是由以下原因引起的:
(1)人行道中非行人实体的流通
(2)异常行人运动模式
经常发生的异常包括骑自行车的人,滑冰者,小推车以及走过人行道或周围草地的人。还记录了一些坐在轮椅上的人的例子。所有异常都是自然发生的,即它们不是为了组装数据集而分期的。
数据集下载 官方地址:UCSD 异常检测数据集 (tar.gz 文件, 707MB, 最后更新时间: 02/27/2013)
(MD5 校验和: 5006421b89885f45a6f93b041145f2eb)
百度网盘:由于文件很大,下载起来非常慢(我下载了一整天),这里我分文件压缩后存在百度网盘里,不知道下载起来是不是更快一些
链接:https://pan.baidu.com/s/1NDR0-M4SQD1m9k9n5lvAow 提取码:nsbn
问题:
相比于 WIN10 专业版来说,WIN10 家庭版在 “启用或关闭Windows功能” 中找不到 Hyper-V 选项。
但这并不意味着 WIN10 家庭版不支持 Hyper-V 功能,我们可以手动开启它。
解决办法:
1、首先要确定电脑是否支持 Hyper-V 功能。
打开 Windows PowerShell,输入 systeminfo 命令:
可以看到出现了很多处理器的信息,最末尾有个 Hyper-V 要求,如果四个全是 “是”,则表示支持 Hyper-V 功能。
2、确定好之后,新建一个文本文档,文件名自取,将下面代码复制进文档中。
pushd "%~dp0" dir /b %SystemRoot%\servicing\Packages\*Hyper-V*.mum >hyper-v.txt for /f %%i in ('findstr /i . hyper-v.txt 2^>nul') do dism /online /norestart /add-package:"%SystemRoot%\servicing\Packages\%%i" del hyper-v.txt Dism /online /enable-feature /featurename:Microsoft-Hyper-V-All /LimitAccess /ALL 3、将文档后缀 .txt 改成 .cmd,之后以管理员身份运行这个文件,等待程序运行结束,重启后生效,之后就可以在 “启用或关闭Windows功能” 中看到 Hyper-V 选项。
————————————————
版权声明:本文为CSDN博主「幽篁晓筑」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
▼看完本文,你可以掌握哪些知识 ↵ 1.git是什么?我们为什么要了解git?
2.git如何新建远程仓库。
3.如何将远程仓库克隆到本地。
4.如何查找仓库下载地址。
5.如何将本地内容更新到远程仓库。
6.如何实现团队协作开发。
▎下载git 官网下载地址☞:https://git-scm.com/
⑴ windows系统下载直接全部点击下一步就可以。 ⑵ 右键显示如图即下载成功
一、git是什么?我们为什么要了解git↵ ①. git是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。 也是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。
②. 掌握git可以让我们在团队内达到和成员协作开发的目的。
③. 在工作场景中会经常使用到git。
二、git如何新建远程仓库↵ ①. 进入gitee网站☞:Gitee - 基于 Git 的代码托管和研发协作平台
②. 进入网站-点击我的-右侧加号-新建仓库。
③. 按照下列步骤进行操作。
③.如果你的浏览器跳转到下图位置,那么恭喜你创建成功了,接下来你就进行上传文件和拉取文件了
三.如何将远程仓库克隆到本地↵ ①. 在本地新建一个文件夹并进入。
②. 右键选择 Git Bash Here ③.在git命令行输入 git clone 远程下载的地址,然后回车
四.如何查找仓库下载地址↵ ①. 进入gitee网站首页-点击我的-选择到我的文件-
②. 点击克隆/下载-选择HTTPS-复制即可。
五、如何将本地内容更新到远程仓库↵ ①. 点击文件夹右键进入命令行 -- Git Bash Here
②.git init 创建一个仓库文件夹
③.git status 检测当前目录文件 ///如果内容在暂存区则显示绿色,内容在工作区则显示红色
④. 在命令行输入【 git add .
对于一个画完的PCB,我们常常需要进行DRC检查,确保板子的电器连接及制作工艺在设定规则的范围内,本篇将介绍如何对PCB进行后期DRC检查处理,确保电路板出现不必要错误。
1.DRC检查入口 2.DRC设置 3.错误分析 对于错误的内容,依据个人实际情况不同,其出现的原因都是因为与设计规则中的设定标准冲突,这里按遇到的错误进行修改讲解,其他错误同理。 4.常见错误分析及解决方法 (1) 解决方法:将未连接网络连接(PCB上未连接的网络都会以细实线作为提示连接线)
(2) 解决方法:设计->规则
(3)间距问题 解决方法:设计->规则 (4)其他问题都可从冲突报告中找到对应报错项,然后设计->规则中合理设定即可
“别动方块”完整代码 #include <graphics.h> #include <conio.h> #include <stdio.h> int main() { float width,height,gravity; // 游戏画面大小、重力加速度 float ball_x,ball_y,ball_vy,radius; // 小球圆心坐标、y方向速度、半径大小 float rect_left_x,rect_top_y,rect_width,rect_height,rect_vx; // 方块障碍物的相关参数 int score = 0; // 得分 int isBallOnFloor = 1; // 小球是否在地面上,避免重复起跳 width = 600; // 游戏画面宽度 height = 400; // 游戏画面高度 gravity = 0.6; // 重力加速度 initgraph(width, height); // 新建一个画布 radius = 20; // 小球半径 ball_x = width/4; // 小球x位置 ball_y = height-radius; // 小球y位置 ball_vy = 0; // 小球初始y速度为0 rect_height = 100; // 方块高度 rect_width = 20; // 方块宽度 rect_left_x = width*3/4; // 方块左边x坐标 rect_top_y = height - rect_height; // 方块顶部y坐标 rect_vx = -3; // 方块x方向速度 while(1) // 一直循环 { if (kbhit()) // 当按键时 { char input = _getch(); // 获得输入字符 if (input==' ' && isBallOnFloor==1) // 当按下空格键,并且小球在地面上时 { ball_vy = -17; // 给小球一个向上的速度 isBallOnFloor = 0; // 表示小球不在地面了,不能重复起跳 } } ball_vy = ball_vy + gravity; // 根据重力加速度更新小球y方向速度 ball_y = ball_y + ball_vy; // 根据小球y方向速度更新其y坐标 if (ball_y >= height-radius) // 如果小球落到地面上 { ball_vy = 0; // y速度为0 ball_y = height-radius; // 规范其y坐标,避免落到地面下 isBallOnFloor = 1; // 表示小球在地面上 } rect_left_x = rect_left_x + rect_vx; // 方块向左移 if (rect_left_x <= 0) // 如果方块跑到最左边 { rect_left_x = width; // 在最右边重新出现 score = score + 1; // 得分+1 rect_height = rand() % int(height/4) + height/4; // 设置随机高度 rect_vx = rand()/float(RAND_MAX) *4 - 7; // 设置方块随机速度 } // 如果小球碰到方块 if ((rect_left_x <= ball_x + radius) && (rect_left_x + rect_width >= ball_x - radius) && (height - rect_height <= ball_y + radius) ) { Sleep(50); // 慢动作效果 score = 0; // 得分清零 } cleardevice(); // 清空画面 fillcircle(ball_x, ball_y, radius); // 绘制小球 // 画方块 fillrectangle(rect_left_x, height - rect_height, rect_left_x + rect_width,height); TCHAR s[20]; // 定义字符串数组 _stprintf(s, _T("
语音识别器 环境主要包 环境展示写作过程1.导入相关包2.定义类来创建隐马尔科夫模型3.定义一个函数来解析其中的命令4.定义主函数5.运行,这里运行是在终端进行运行的。 注意事项参考书籍代码参考基础知识学习 完整代码 环境 这里我用的linux下kali虚拟机。 Anaconda环境,pycharm编译器。python3.6.13 主要包 # 直接就是清华源下载,清华源是真的好用,谁用谁知道 pip install --user -i https://pypi.tuna.tsinghua.edu.cn/simple numpy pip install --user -i https://pypi.tuna.tsinghua.edu.cn/simple scipy pip install --user -i https://pypi.tuna.tsinghua.edu.cn/simple hmmlearn pip install --user -i https://pypi.tuna.tsinghua.edu.cn/simple python_speech_features 环境展示 这里用到的单词音频就是我们上篇通过文字发音保存的音频。
写作过程 1.导入相关包 # 利用隐马尔科夫模型进行语音识别 # 隐马尔科夫模型(Hidden Markov Models,HMM) import os import argparse import numpy as np from scipy.io import wavfile from hmmlearn import hmm from python_speech_features import mfcc 2.定义类来创建隐马尔科夫模型 # 1.定义一个类来创建隐马尔科夫模型 class HMMTrainer(object): # 初始化类。下面用到高斯隐马尔科夫(Gaussion HMMs)来对数据建模。 # 参数n_components定义了隐藏状态的个数,参数cov_type定义了转移矩阵的协方差类型,参数n_iter定义了训练的迭代次数 def __init__(self, model_name='GaussianHMM', n_components=4, cov_type='diag', n_iter=1000): # 初始化变量 self.
计算电磁参考数目:ppt(相关ppt见上传资料)
计算电磁学包括有限差分法,有限元法,时域有限差分法,矩量法。
首先是有限差分法
有限差分法主要解决静态电磁场问题。它的思路是根据已知静态边值求解内部的场分布。将定解区域离散化为网格离散节点的集合,并以各离散点上的函数差商来近似该点的偏导数,根据差分方程组求解各离散点处的待求函数值,离散解。
它求解的是泊松方程(泊松方程是静态场方程,和时间无关,有源就是泊松方程,无源就是拉普拉斯方程)。泊松方程的五点差分格式。记住不同煤质上的差分格式。记住定解条件的离散化。
计算步骤:离散场域,离散化场方程,计算离散解。
前面是离散场域和离散化场方程,后面是计算离散解。
离散解可以直接法解矩阵方程,也可以用迭代法。迭代法有雅可比迭代法,高斯赛德尔迭代法和超松弛迭代法。最常用的是超松弛迭代法,他的松弛因子w常用公式要记住。
有限差分法可以想象成,一个长方形区域,已知四边的温度,求整个区域的热分布。迭代法就是从边慢慢计算靠近边的一些点最后计算完整个区域,然后再来一遍,直到出现前后两次计算结果一致(误差在一个范围内)
然后是有限元法
有限元法的本质是有限差分法和变分法的结合(变分法:把求解矩阵问题转化为求解极值问题)。有限元法求解的也是静态场问题,根据有无源(泊松方程和拉普拉斯方程),以及三类边界条件,可以将这六类问题的求解分别对应六种极值问题。也就是说根据变分原理,能够将边值问题转化为对应的变分问题。最简单的是拉普拉斯方程和第一类边界条件。
有限元法的步骤为:
刚才是第一步
第二步场域剖分问题,有限元法通常把场域剖分为三角形(和其他剖分为矩形不同),剖分要注意8个原则,根据这个原则,平常只用直线内插法,注意直线内插法是咋编号的
剖分之后涉及两个概念,一个叫形状函数,形状函数是个啥东西呢,它表示三角形内某一点的值和三个顶点的值之间的关系,也就是用三个顶点的值来表示三角形内任意一点的值,也叫做插值函数。由于它和单元的形状大小,插值函数等等有关,称它为形状函数。另一个叫系数矩阵k,单元的总能量(各个点的值的和可以根据插值函数用三个顶点表示出来),这个能量和三个点的值的关系就叫单元的系数矩阵,整个区域的总能量,总泛函可以用各个顶点和整体总系数矩阵k表示,总系数矩阵是各个单元的系数矩阵相连,重合点叠加的结果。
整体泛函(求最大值)问题可以转化为泛函导数等于0的问题,因此泛函的解为kfai=0(拉普拉斯方程)或者kfai=p(泊松方程)。求解这个方程即可
求解的方法有直接法和迭代法,主要使用直接法中的高斯消去法,这是个神奇的方法,首先强加边界条件,然后顺追赶过程,然后逆追赶过程。
有限元法整个过程可以总结为:首先将边值问题转化为对应的变分问题,剖分单元并编号,然后第二步计算系数矩阵k,然后构成有限元方程,进而进行强加边界条件处理,高斯消去法解出。
hfss用的就是有限元法,优点是计算精确,缺点是计算慢的一匹
然后是fdtd
重磅推出时域有限差分法fdtd,这个课不止在电磁学里用,在热学和其他研究里应用也广的一匹。相比于计算静态场的有限元法和有限差分法,fdtd是计算时变场的。它的计算方式也很硬核。因为它的方程和fd,fem不同。fd和fem是静电场,它们麦克斯韦方程里没有时变项,因此可以简化为泊松方程或者拉普拉斯方程。只要解无时间项的泊松方程或者拉普拉斯方程就好,它们最后的解是一个静止的电场分布图,相当于一幅静态的画。但是对于fdtd解决的问题是时变场的问题,它求解的方程是麦克斯韦方程,最后的解是不同时间的电场分布,相当于一个电影,由一帧一帧构成。它的思路相当彪悍,是把电磁场在时间上和空间上都离散化(具体离散时间间隔和空间离散点选取后面说),然后交叉半步法推进,即计算这一帧的电场,再计算下一帧的磁场,再由这个磁场计算下下一帧的电场,以此交叉推进。
离散点的选取:e选在棱上,h选在面中心。时间上:e是n时刻,h是n+1/2时刻。
要掌握麦克斯韦方程这样离散的推导方法
掌握收敛性和稳定性的定义(收敛性:离散间隔趋近于0时,解趋近准确解。稳定性:离散间隔取一定值,解和准确解之间差有界)
掌握时间空间稳定性的要求,为啥要有时间最小和空间最小要求?时间:可以理解为时间跨度太大会掉帧,空间:可以理解为网格划太大仿的不准。
空间划分:散射计算的连接边界,吸收边界和输出边界。辐射计算的输出边界和吸收边界
掌握几种吸收边界定义:mur,pml,enquist等等
例题
cst用的是fdtd,优点是算的快
最后是矩量法
矩量法
基本思想是内域积加权余量法,将连续方程化成代数方程组。
用矩量法解算子方程L(f)=g的基本步骤
1.离散化,把未知函数f表示成一组基函数的代数和形式,这样求解f就变成求每个基函数的系数an了
2.取样检验,选择一组权函数(又叫检验函数)wm,将wm取内积抽样检验,化成矩阵方程
3.矩阵求逆,得an
基函数可以分为全域基和分域基,权函数可以分为全域权,分域权和点选配。权函数和基函数相等叫伽辽金法。
全域基的优点是收敛快,缺点是难找合适的基函数。分域基的优点是简单灵活,不受未知函数约束,缺点是收敛慢
可以这样理解矩量法:当时做dda的时候,每个缝隙需要等效进行场积分,这个缝隙场积分的值就是未知函数f等效成一个磁偶极子。因为缝隙很长,用一个磁偶极子等效不精确,可以分段,用多个磁偶极子等效。每段可以看成一个门函数,求解积分就等效成求解每段门函数的系数矩阵an了,知道了an,求和就能知道f。这就是把待求量离散化。怎么抽样检验呢,已知它在波导外某个点的辐射场的值g,用这个来构建方程求解an。这儿的算子L就是格林函数。但是只有一个点不行啊,一个点只能建立一个方程,求不出n个an,所以选n个点的值建立n个方程就好了。这种选取权函数的方法叫点选配。
电磁场与电磁波基础知识复习:
https://www.bilibili.com/video/BV1ff4y1y7TE?spm_id_from=333.999.0.0
偏微分方程介绍:
https://www.bilibili.com/video/BV1q4411p7NX?spm_id_from=333.999.0.0
有限差分法fd:https://www.bilibili.com/video/BV1Nh41197Tt?spm_id_from=333.999.0.0
有限元法fem:https://www.bilibili.com/video/BV1dN411f7NU?spm_id_from=333.999.0.0
https://www.bilibili.com/video/BV1tq4y1j7f1?spm_id_from=333.999.0.0
时域有限差分法fdtd:
https://www.bilibili.com/video/BV1Sg4y1q7qD?spm_id_from=333.999.0.0
https://www.bilibili.com/video/BV1jb4y127BJ?spm_id_from=333.999.0.0
https://www.bilibili.com/video/BV1gA411e7kM?spm_id_from=333.999.0.0
https://www.bilibili.com/video/BV1qi4y177Kp?spm_id_from=333.999.0.0
单词发音,为语音识别准备素材 环境windows下安装pyttsx3linux下安装pyttsx3 界面展示图形化界面输出文档 写作过程注意事项完整代码 环境 这里我用的是python3.7.9。pycharm编译器。windows系统。 windows下安装pyttsx3 pip install pyttsx3 linux下安装pyttsx3 linux下安装pyttsx3时,要先安装两个插件,要不用起来会报错 sudo apt-get install alsa-utils sudo apt-get install espeak pip install pyttsx3 界面展示 图形化界面 图形化界面,很简陋的一个
输出文档 是我做好之后的音频素材文档
保存单词的word.txt
单词发音
写作过程 1.导入相关包。
os,用来进行文件的读写。re,正则匹配。pyttsx3,文字读语音。
import os import tkinter from tkinter.filedialog import * from tkinter import ttk import pyttsx3 import re 2.这里我准备了一个类来做图形化界面,函数功能也直接在类里面实现了。结果就是看起来十分臃肿,一点都不美观。不过这解决了函数放在类外面出现的一些问题。比如说变量调用很麻烦之类的。
里面变量有些数字大的在前面,这是因为我写的时候是按照从小到大开始写的,但刚开始有些功能没有想明白,把新代码插在了中间。
self.path: 存放文件的输入框
self.path1: 单词的输入框
self.language: 选择发音
self.prompt_statement: 提示语句
self.batch_file: 批文件的输入框。文件里面存放多个英文单词
self.words: 文件里面的单词数量
class painting(): def __init__(self): self.app1 = tkinter.
什么是组件?
组件的出现,就是为了拆分Vue实例的代码量的,能够让我们以不同的组件,来划分不同的功能模块,将来我们需要什么样的功能,就可以去调用对应的组件即可。
组件化和模块化的不同:
模块化:是从代码逻辑的角度进行划分的;方便代码分层开发,保证每个功能模块的职能单一
组件化:是从UI界面的角度进行划分的;前端的组件化,方便UI组件的重用
全局组件定义的四种方式:
使用 Vue.extend 配合 Vue.component 直接使用 Vue.component
将模板字符串,定义到script标签中,同时,需要使用 Vue.component 来定义组件
将模板字符串,定义到template标签中,同时,需要使用 Vue.component 来定义组件(一般都是使用这种方式)
如图:
局部组件使用components属性定义:
使用:is属性可以切换不同的子组件:
什么是插槽?
插槽就是子组件中的提供给父组件使用的一个占位符,用<slot></slot> 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的<slot></slot>标签。
例:
具名插槽:具名插槽其实就是给插槽娶个名字。一个子组件可以放多个插槽,而且可以放在不同的地方,而父组件填充内容时,可以根据这个名字把内容填充到对应插槽中。
例:
题目描述 本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
X 星球的盛大节日为增加气氛,用 30 台机光器一字排开,向太空中打出光柱。
安装调试的时候才发现,不知什么原因,相邻的两台激光器不能同时打开! 国王很想知道,在目前这种 bug 存在的情况下,一共能打出多少种激光效果?
显然,如果只有 3 台机器,一共可以成 5 种样式,即: 全都关上(sorry, 此时无声胜有声,这也算一种);开一台,共 3 种;开两台,只 1 种。
30 台就不好算了,国王只好请你帮忙了。
要求输出一个整数,表示 30 台激光器能形成的样式种数。
运行限制 最大运行时间:1s最大运行内存: 128M //2 //3 //5 //8 //13 //打表找规律 #include<iostream> using namespace std; int Fib(int n) { if(n == 1) return 2; if(n == 2) return 3; return Fib(n - 1) + Fib(n - 2); } int main() { int n = Fib(30); cout << n << endl; } //递归搜索 #include<iostream> using namespace std; long long ans = 0; int sta[33]; void dfs(int x) { if(x == 31){ ans++; return ; } dfs(x + 1);//这个灯关的 if(sta[x - 1] == 0) { sta[x] = 1; //打开这个灯,向下搜索 dfs(x + 1); sta[x] = 0; } return ; } int main() { dfs(1); cout << ans << endl; return 0; }
借鉴:tensorflow中的Graph(图)和Session(会话)的关系 - 简书
借鉴:TensorFlow学习笔记1:graph、session和op - Jiax - 博客园
一、Graph和Session的关系 TensorFlow是一种“符号式编程框架”,首先要构造一个图(graph),然后在会话(Session)上根据这个图做真实的运算(op)。打个比方,graph就是“输入-处理-输出”这个pipeline中的处理部分,一个session就是建立了一个pipeline进行“输入-处理-输出”。graph具有一系列的加工步骤(加减乘除等运算),session把输入投进去,就能得到输出。不同的session都可以使用同一个graph,只要他们的加工步骤是一样的就行。同样的,一个graph可以供多个session使用,而一个session不一定需要使用graph的全部,可以只使用其中的一部分。
graph即tf.Graph(),session即tf.Session(),是两个完全独立的概念。
graph定义了计算方式,是一些加减乘除等运算的组合。它本身不会进行任何计算,也不保存任何中间计算结果。session用来运行一个graph,或者运行graph的一部分。它类似于一个执行者,给graph灌入输入数据,得到输出,并保存中间的计算结果。同时它也给graph分配计算资源(如内存、显卡等) 下图是用tensorflow制作大盘鸡和红烧肉的过程,以此为例来说明graph和session的区别:
左图中绿色矩形为数据,黄色圆圈为中间结果,红色圆圈为最终结果,这是一个完整的制作大盘鸡和红烧肉的graph(相当于是一个菜谱),图中每一个独立单元都可以看成是一个op(操作,包括数据)。在tensorflow中只有graph是没法得到结果的,这就像只有菜谱不可能得到红烧肉是一个道理。于是就有了tf.Session(),他根据graph制定的步骤,将graph变成现实。
tf.Session()就相当于一个厨师长,他下面有很多办事的人(Session()下的各种方法),其中有一个非常厉害人叫tf.Session.run(),他不仅会烧菜,还会杀猪、酿酒、制作酱料等一系列工作,比如:
我的酱料 = sess.run(酱料):run收到制作“酱料”的命令,于是他看了下graph,需要“酵母”和“大豆”来制作酱料,最终他把酱料制作好了(这里酵母和大豆是graph定义好的,但也可以根据自己的喜好来换)。
我的料酒 = sess.run(料酒,feed_dic={米:泰国籼米}):run又收到要制作“料酒”的命令,而且不用graph规定的“米”来做,需要用“泰国籼米”,没关系,run跑去买了泰国籼米,又把料酒给做了。
我的红烧肉 = sess.run(红烧肉):傍晚,run又收到了做一份完整红烧肉的命令,这下他有的忙了,必须将整个流程走一遍,才能完成个任务。
我的大盘鸡 = sess.run(大盘鸡): 后来,run又收到做大盘鸡的任务,这是一个独立的任务,跟红烧肉没有半点关系,但不影响,他只要按照步骤照做就可以了。
二、关于Graph 2.1 定义一个图:graph #定义一个graph g = tf.Graph() #默认在g中定义下面op a = tf.constant(2) b = tf.constant(3) x = tf.add(a, b) 上面就定义了一个graph。tensorflow会默认给我们建立一个graph,所以g = tf.Graph()这句其实是可以省略的。上面的graph包含3个操作(即op),但凡是op,都需要通过session运行之后,才能得到结果。如果你直接执行print(a),那么输出结果是:Tensor("a:0", shape=(), dtype=int32)。执行print(tf.Session().run(a))或with方法,才能得到2。可见,在tensorflow中,即使是最基本的对象Tensor(张量)也需要在Session中才能得到其值
2.2 定义多个图:多个graph 你可以定义多个graph,例如一个graph实现z = x + y,另一个graph实现u = 2 * v
g1 = tf.Graph() #定义一个graph g2 = tf.Graph() #定义另一个graph with g1.
原文链接:https://blog.csdn.net/qq_37896578/article/details/109327813
<script> document.addEventListener('keydown', function (event) { if ((event.ctrlKey === true || event.metaKey === true) && (event.which === 61 || event.which === 107 || event.which === 173 || event.which === 109 || event.which === 187 || event.which === 189)) { event.preventDefault(); } }, false); // Chrome IE 360 window.addEventListener('mousewheel', function (event) { if (event.ctrlKey === true || event.metaKey) { event.preventDefault(); } }, { passive: false }); //firefox window.addEventListener('DOMMouseScroll', function (event) { if (event.
园区网络三层架构 随着企业信息化建设不断深入,企业的生产业务系统、经营管理系统、办公自动化系统均得到大力发展,对于企业园区网的建设要求越来越高。传统园区网建设初期往往面临如下问题: 1、网络架构较为混乱,不便于扩容和维护管理
2、 网络可靠性规划不合理,影响企业生产和经营管理、造成投资浪费
3、网络信息安全存在隐患
4、无法满足日益增长的网络业务需求
5、缺乏简单有效的网络管理系统,企业IT网络运维部门面临很大压力
园区网络结构多趋向于模块化、结构化,接入层按接入人数或者部门划分。
网关多放在汇聚层
接入层
接入层交换机一般部署在楼道的网络机柜中,接入园区网用户(PC机或服务器),提供二层交换机功能,也支持三层接入功能(接入交换机为三层交换机)。
由于接入层交换机直接接园区网用户,根据用户接入信息点数目和类型(GE/FE),对接入交换机的GE/FE接口密度有较高的要求。另外接入交换机部署在楼道网络机柜,数量大,对于成本、功耗和易管理维护等特性要求较高。
汇聚层
园区汇聚层交换机一般部署在楼宇独立的网络汇聚机柜中,汇聚园区接入交换机的流量,一般提供三层交换机功能,汇聚层交换机作为园区网的网关,终结园区网用户的二层流量,进行三层转发。
根据需要,可以在汇聚交换机上集成增值业务板卡(如防火墙,负载均衡器、WLAN AC控制器)或者旁挂独立的增值业务设备,为园区网用户提供增值业务,汇聚交换机需要提供高密度的GE接口,汇聚接入交换机的流量,通过10GE接口接到核心交换。
核心层
园区核心层交换机部署在园区核心机房中,汇聚各楼宇/区域之间的用户流量,提供三层交换机功能,连接园区外部网络到内部用户的“纵向流量”和不同汇聚区域用户之间的“横向流量”要求高密10GE、高转发性能。
出口层
园区出口路由器,连接Internet/WAN广域网和园区内部局域网。
接下来,我们来搭建配置一个园区网络实例,网关在汇聚层,网络高冗余性。 结构拓扑:
配置思路(以区域2为例): 从接入层开始,先划分vlan
LSW16-LSW19为 vlan 2 - 10 ,LSW20 - LSW23为 vlan 11 - 19,具体vlan划分如图所示。
划分完后,将接入交换机进行逐一配置,把接入层接口划分到vlan中,并配置边缘接口。
vlan batch 11-19 # 以区域二的LSW20为例 port-group group-member g0/0/3 to g0/0/10 port link-type access port default vlan 11 stp edged-port enable port-group group-member g0/0/11 to g0/0/20 port link-type access port default vlan 12 stp edged-port enable port-group group-member g0/0/1 to g0/0/2 port link-type trunk undo port trunk allow-pass vlan 1 #防止环路 port trunk allow-pass vlan 11 to 12 其余设备根据vlan划分,把自己的接口划分到相对应的vlan中,修改以上的vlan数据即可,此处不作过多赘述。
目录
线程概念:
线程之间的独有与共享:
多线程与多进程在多任务处理中的优缺点:
线程控制:
线程创建:
线程终止:
线程等待:
线程分离:
线程安全(的问题):
*互斥锁:
*死锁: *同步:
*条件变量:
设计模式 (多线程的应用): 生产者与消费者模型
*信号量(POSIX):posix标准信号量:
*线程池的简单实现:
*线程安全的单例模式:
线程概念: 线程是进程中的一条执行流程.
在linux之前学习进程的时候 ,进程就是一个pcb, 但是在现在学习线程的时候, 发现线程是进程中的一条执行流,而因为linux下执行流是通过pcb来完成的,所以理解pcb是linux下的执行流,反推得到了一个结论,linux下的一个pcb是一个线程。只不过人家linux下通常不谈线程,而叫做轻量级进程. ( 有些地方认为Linux没有真正的线程的说法, 线程实际上是一个轻量级进程. )
从另一个角度来说:
线程是cpu调度的基本单位, 进程是资源分配的基本单位.
线程之间的独有与共享: 共享(每个线程相同的): 虚拟地址空间(使线程间可以直接通信).
信号处理方式(信号是针对进程的, 当给一个进程发送一个信号时, 所有的线程都能收到这个信号, 处于cpu时间片上运行的线程会处理这个信号, 某个地方修改了这个信号的处理方式则其他线程对这个信号的处理方式也跟着修改了.). io信息(共享文件描述信息, 可以操作同一文件, 而且不同的线程的文件读写位置是一致的, 常见的设计思路是 有一个线程专门负责打开文件, 后续其他线程负责文件的各种操作).
工作路径( 比如在三级目录下运行一个open(./text, O_CREATE,664)的test程序则text文件生成在当前三记录下. 如果在二级目录下运行这个test程序: ./三级目录名/test 运行则text文件生成在当前的二级目录下)等...
独有(线程之间不同的):
栈( 局部变量存放在栈中, 但是把局部变量的地址给其他线程, 其他线程也能访问到该变量,因为虚拟地址空间是同一套的.).
上下文数据(即寄存器独有pcb是不断在切换运行的, 为了保存不同线程自己每次运行到哪了,下次时间片运行时接着运行,所以每个线程有自己的上下文数据.).
errno(不同线程用接口操作时某个可能失败了, 某个成功了, errno独有则保证了不发生冲突).
信号屏蔽字(即信号阻塞集合, 线程信号会打断当前操作, 为了保护某些线程正常运行, 就算此线程拿到时间片也不去处理信号. 所以线程之间信号阻塞集合是独有的).
线程id等...
文章目录 一、SpringMVC简介1、什么是MVC2、什么是SpringMVC3、SpringMVC的特点 二、HelloWorld1、开发环境2、创建maven工程a>添加web模块b>打包方式:warc>引入依赖 3、配置web.xmla>默认配置方式b>扩展配置方式 4、创建请求控制器5、创建springMVC的配置文件6、测试HelloWorlda>实现对首页的访问b>通过超链接跳转到指定页面 7、总结 8、bug总结8.1thymeleaf依赖 三、@RequestMapping注解1、@RequestMapping注解的功能2、@RequestMapping注解的位置3、@RequestMapping注解的value属性4、@RequestMapping注解的method属性5、@RequestMapping注解的params属性(了解)6、@RequestMapping注解的headers属性(了解)7、SpringMVC支持ant风格的路径8、SpringMVC支持路径中的占位符(重点) 四、SpringMVC获取请求参数1、通过ServletAPI获取2、通过控制器方法的形参获取请求参数3、@RequestParam4、@RequestHeader5、@CookieValue6、通过POJO获取请求参数7、解决获取请求参数的乱码问题 五、域对象共享数据1、使用ServletAPI向request域对象共享数据2、使用ModelAndView向request域对象共享数据3、使用Model向request域对象共享数据4、使用map向request域对象共享数据5、使用ModelMap向request域对象共享数据6、Model、ModelMap、Map的关系7、向session域共享数据8、向application域共享数据 六、SpringMVC的视图1、ThymeleafView2、转发视图3、重定向视图4、视图控制器view-controller 七、RESTful1、RESTful简介a>资源b>资源的表述c>状态转移 2、RESTful的实现3、HiddenHttpMethodFilter 八、RESTful案例1、准备工作2、功能清单3、具体功能:访问首页a>配置view-controllerb>创建页面 4、具体功能:查询所有员工数据a>控制器方法b>创建employee_list.html 5、具体功能:删除a>创建处理delete请求方式的表单b>删除超链接绑定点击事件c>控制器方法 6、具体功能:跳转到添加数据页面a>配置view-controllerb>创建employee_add.html 7、具体功能:执行保存a>控制器方法 8、具体功能:跳转到更新数据页面a>修改超链接b>控制器方法c>创建employee_update.html 9、具体功能:执行更新a>控制器方法 八、HttpMessageConverter1、@RequestBody2、RequestEntity3、@ResponseBody4、SpringMVC处理json5、SpringMVC处理ajax6、@RestController注解7、ResponseEntity 九、文件上传和下载1、文件下载2、文件上传 十、拦截器1、拦截器的配置2、拦截器的三个抽象方法3、多个拦截器的执行顺序 十一、异常处理器1、基于配置的异常处理2、基于注解的异常处理 十二、注解配置SpringMVC1、创建初始化类,代替web.xml2、创建SpringConfig配置类,代替spring的配置文件3、创建WebConfig配置类,代替SpringMVC的配置文件4、测试功能 十三、SpringMVC执行流程1、SpringMVC常用组件2、DispatcherServlet初始化过程a>初始化WebApplicationContextb>创建WebApplicationContextc>DispatcherServlet初始化策略 3、DispatcherServlet调用组件处理请求a>processRequest()b>doService()c>doDispatch()d>processDispatchResult() 4、SpringMVC的执行流程 一、SpringMVC简介 1、什么是MVC MVC是一种软件架构的思想,将软件按照模型、视图、控制器来划分
M:Model,模型层,指工程中的JavaBean,作用是处理数据
JavaBean分为两类:
一类称为实体类Bean:专门存储业务数据的,如 Student、User 等一类称为业务处理 Bean:指 Service 或 Dao 对象,专门用于处理业务逻辑和数据访问。 V:View,视图层,指工程中的html或jsp等页面,作用是与用户进行交互,展示数据
C:Controller,控制层,指工程中的servlet,作用是接收请求和响应浏览器
MVC的工作流程:
用户通过视图层发送请求到服务器,在服务器中请求被Controller接收,Controller调用相应的Model层处理请求,处理完毕将结果返回到Controller,Controller再根据请求处理的结果找到相应的View视图,渲染数据后最终响应给浏览器
2、什么是SpringMVC SpringMVC是Spring的一个后续产品,是Spring的一个子项目
SpringMVC 是 Spring 为表述层开发提供的一整套完备的解决方案。在表述层框架历经 Strust、WebWork、Strust2 等诸多产品的历代更迭之后,目前业界普遍选择了 SpringMVC 作为 Java EE 项目表述层开发的首选方案。
注:三层架构分为表述层(或表示层)、业务逻辑层、数据访问层,表述层表示前台页面和后台servlet
3、SpringMVC的特点 Spring 家族原生产品,与 IOC 容器等基础设施无缝对接基于原生的Servlet,通过了功能强大的前端控制器DispatcherServlet,对请求和响应进行统一处理表述层各细分领域需要解决的问题全方位覆盖,提供全面解决方案代码清新简洁,大幅度提升开发效率内部组件化程度高,可插拔式组件即插即用,想要什么功能配置相应组件即可性能卓著,尤其适合现代大型、超大型互联网项目要求 二、HelloWorld 1、开发环境 IDE:idea 2019.2
构建工具:maven3.5.4
简介 Spring5框架
内容介绍:
1.Spring概念
2.IOC容器
3.Aop
4.JDBCTEmplate
5.事物管理
6.Spring5新特性
所需的jar包
参考俺滴下面博客
Spring所需jar包_爱你的阿白~的博客-CSDN博客
一.Spring框架概述 1.概述 1.Spring框架是轻量级的JavaEE框架
2.Spring可以解决企业应用开发的复杂性
3.Spring有两个核心部分:IOC和Aop
(1)IOC:控制反转,把创建对象的过程交给Spring进行管理
(2)Aop:面向切面,不修改源代码进行功能增强
4.Spring特点
(1)方便解耦,简化开发
(2)Aop变成支持
(3)方便程序测试
(4)方便和其他框架进行整合
(5)方便进行事物操作
(6)降低API开发难度
5.Spring5
2.入门案例 (1)下载spring 最后是这个网址
https://repo.spring.io/ui/native/release/org/springframework/spring/ 下载解压
(2)创建新的项目 (3)导入jar包 把所需的jar包导入其中
导入流程:
在项目文件夹中建立lab文件夹
把jar包放入文件夹中
(4)创建普通类 在这个类中创建普通方法
(5)创建Spring配置文件 在配置文件中配置创建的对象
1.Spring配置文件使用xml文件格式
(6)测试代码编写 二,IOC容器 1.IOC底层原理 (1)什么是IOC 控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。 one:控制反转,把对象的创建和对象的调用过程交给Spring进行管理
two:使用IOC的目的:为了耦合度降低
three:做入门案例就是IOC的实现
(2)IOC底层原理 (1)xml解析,工厂模式,反射
(3)画图讲解IOC底层原理 IOC过程
(1)配置xml文件,配置创建的对象
(2)有service类和dao类,创建工厂类
2.IOC接口(BeanFactory) 1.IOC思想基于IOC容器完成,IOC容器底层就是对象工厂
2.Spring提供IOC容器实现的两种方式:(两个接口)
(1)BeanFactory:
IOC容器中最基本实现方式,时Spring内部使用的接口,不提供开发人员进行使用
特点:加载配置文件的时候不会去创建对象,在获取对象(使用)才会去创建对象
(2)ApplicationContext:
BeanFactory接口的子接口,提供更多更强大的功能,一般有开发人员进行使用
软考考试一共有27个专业资格,涵盖5个专业领域, 3个级别层次(初级、中级、高级)。
含金量:高级>中级>初级
难度:高级>中级>初级
证书有效期:永久有效
如何选择考试科目? 1.根据自己的兴趣选择,俗话说:兴趣是最好的老师,相信自己会学的很好!
以下是软考五大专业领域里比较火,用处较大的专业资格考试:
计算机软件:软件评测师、软件设计师
计算机网络:网络工程师
计算机应用技术:多媒体应用设计师、嵌入式系统设计师、电子商务设计师
信息系统:系统集成项目管理工程师、信息系统监理师、信息安全工程师、数据库系统工程师、信息系统管理工程师
信息服务:计算机硬件工程师、信息技术支持工程师
2.如果只是为了抵扣个税、积分落户和评职称,那么建议考一个系统集成项目管理工程师或者信息系统项目管理师。
(注意:后者难度会比前者大,但含金量也更高。在积分落户政策上,后者加分更多;在评职称上,后者可以评副高级职称,前者则是中级职称)
3.如果公司鼓励,并且有相对应的奖励机制,建议优先考虑软考中级,毕竟难度较低。当然最后还是要看公司具体要求。
4.如果是为了提升自己,在工作中有进一步的发展,建议考相对应的软考高级证书;其中,如果自己想从技术岗转为管理岗,建议考信息系统项目管理师。
5.如果是相关专业的学生,建议考软考中级,可以根据自己的职业规划选择考试科目,这样在找工作的过程中,自己也有一定的竞争力。
大家可以根据自己的实际情况来选择考试科目,不管选择哪一个它们的含金量都是差不多的,可以放心选择,如果还有什么疑问,欢迎留言哦!
本函数影响由fd 参数引用的一个打开的文件。
#include<unistd.h>
int ioctl( int fd, int request, .../* void *arg */ );
返回0 :成功 -1 :出错
第三个参数总是一个指针,但指针的类型依赖于request 参数。
我们可以把和网络相关的请求划分为6 类:
套接口操作
文件操作
接口操作
ARP 高速缓存操作
路由表操作
流系统
下表列出了网络相关ioctl 请求的request 参数以及arg 地址必须指向的数据类型:
类别
Request
说明
数据类型
套
接
口
SIOCATMARK
SIOCSPGRP
SIOCGPGRP
是否位于带外标记
设置套接口的进程ID 或进程组ID
获取套接口的进程ID 或进程组ID
int
int
int
文
件
FIONBIN
FIOASYNC
FIONREAD
FIOSETOWN
FIOGETOWN
设置/ 清除非阻塞I/O 标志
设置/ 清除信号驱动异步I/O 标志
获取接收缓存区中的字节数
设置文件的进程ID 或进程组ID
获取文件的进程ID 或进程组ID
文章目录 前言一、环境1、SpringBoot 版本2、Mybatis Plus 3.1及以上版本 二、代码步骤一:配置Mybatis Plus枚举方式一: ==配置MybatisPlusAutoConfiguration==方式二: ==配置.yml文件== 步骤二:配置枚举类方式一: ==枚举属性,实现 IEnum,重写getValue()==方式二:==使用 @EnumValue 注解枚举属性== 步骤三:实体中使用Enum 三、测试及结果1、测试数据库Debug中StudentDebug中查询到的StudentList 四、官方网站 前言 状态映射关系太多?使用枚举变量,映射关系交给spring自动维护!!!告别烦恼!!!
一、环境 1、SpringBoot 版本 <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.5.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> 2、Mybatis Plus 3.1及以上版本 <!-- mybatis plus 3.1 以上版本 --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.1</version> </dependency> 二、代码 步骤一:配置Mybatis Plus枚举 方式一: 配置MybatisPlusAutoConfiguration @Configuration public class MybatisPlusAutoConfiguration { /** * 配置Mybatis枚举 * @return */ @Bean public MybatisPlusPropertiesCustomizer mybatisPlusPropertiesCustomizer() { return properties -> { MybatisConfiguration configuration = new MybatisConfiguration(); configuration.
文件上传 文件上传要求form表单的请求方式必须为post,并且添加属性enctype=“multipart/form-data”
SpringMVC中将上传的文件封装到MultipartFile对象中,通过此对象可以获取文件相关信息
缺一不可 1.请求方式必须为post
2.属性enctype=“multipart/form-data”
上传步骤:
a>添加依赖:
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency> b>在SpringMVC的配置文件中添加配置:
<!--必须通过文件解析器的解析才能将文件转换为MultipartFile对象--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean> c>控制器方法:
/** * 实现文件上传功能 * @param photo * @param session * @return * @throws IOException */ @RequestMapping("/testUp") public String testUp(MultipartFile photo, HttpSession session) throws IOException { //获取上传的文件的文件名 String fileName = photo.getOriginalFilename(); //处理文件重名问题 (获取后缀名) String hzName = fileName.substring(fileName.lastIndexOf(".")); fileName = UUID.randomUUID().toString() + hzName; //获取服务器中photo目录的路径 ServletContext servletContext = session.getServletContext(); String photoPath = servletContext.
Windows中jps命令无法查看java进程问题 今天发现公司的电脑输入jps命令无法查看进程,环境变量也都配置好了,就查了下,解决了,想着转载记录下。 版权声明:本文为CSDN博主「无数_mirage」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_43413788/article/details/107772563
原因:在 Windows系统中,每个 java 进程启动之后都在 %TMP%/hsperfdata_${user} (${user}为当前登录用户名) 目录下建立一个以该 java 进程 pid 为文件名的文件,用以记录该 java 进程的一些信息。 通常是因为没有对这个文件的写入权限而导致jps命令查看不到进程
通过环境变量查看%TMP%位置
进入目录找到%TMP%/hsperfdata_${user}
查看属性-安全。发现没有配置当前用户的权限
新增当前用户
再次运行java程序,查看%TMP%/hsperfdata_${user}
执行jps 正常
一、概述 spring-cloud-gateway是一个库,可以在spring webflux之上建立一个API网关,它的目的是提供一个简单,有效的方式去路由到APIS并且提供:安全、监控和弹性。gateway构建于spring boot2.x,spring webFlux,and Project Reactor,所以,许多同步库如spring Data和spring security不适用于gateway项目中。因为gateway是异步非阻塞的。
gateway要求spring boot和spring webFlux提供Netty运行环境。它不能工作在传统的servlet容器或打成一个War包。
二、特点 1、能够对任意的请求属性进行路由匹配
2、能对路由进行断言和过滤
3、集成了熔断器
4、集成了spring-cloud-discoveryclient
5、很容易的写断言和过滤
6、限流
7、路径重写
三、三大组件 1、Route。是构建网关的基本模块,他是ID,目标URL,一系列的断言和过滤器组成,如果断言为true,则匹配该路由
2、Rredicate。参考的是Java8的Predicate,开发人员可以匹配HTTP请求中的所有内容,如果请求与断言相匹配则进行路由
3、Filter。指的是spring框架中GatewayFileter的实例,使用过滤器,可以在请求被路由前由前或者之后对请求进行修改。
四、gateway的工作流程 客户端将请求发给spring cloud gateway,如果gateway handle mapping 确定这个请求和一个路由匹配,它将此请求发给 gateway web handle. 这个 handle 运行这个请求,通过一个filter chain,这个 filter chain在请求路由前后都能执行。
五、gateway的限流 gateway作为网关,与其他网关技术不同的是它能实现限流。gateway使用的是令牌桶算法实现限流。常见的限流算法有:
1、计数器算法:以QPS为100举例,如果1秒钟内钱200ms请求数量到达了100,后面800ms中的请求都会被拒绝,这种情况称为”突刺现象“
2、漏桶算法:可以解决突刺现象。比如创建一个很大的队列来接收请求,一个较小的线程池来处理请求。但是也有极限情况,当队列满了时, 请求也会拒绝掉。
3、令牌桶算法:可以说是漏桶算法的改进。在桶中放令牌,请求获取令牌后才能继续执行。如果桶中无令牌,请求可以选择进行等待或直接拒绝。
在项目中使用gateway网关做限流一般结合的redis,使用令牌桶算法。
六、gateway的断言 gateway包含了许多内置的路由断言工厂。所有的这些断言匹配不同的HTTP请求属性。你能组合这些路由断言工厂。我们一般是在配置文件中配置predicates,当然我们也可以自定义Predicate,如下:
@Component public class CustomeRoutePredicateFactory extends AbstractRoutePredicateFactory<PathRoutePredicateFactory.Config> { public CustomeRoutePredicateFactory() { super(PathRoutePredicateFactory.Config.class); } @Override public Predicate<ServerWebExchange> apply(PathRoutePredicateFactory.Config config) { System.out.println("TokenRoutePredicateFactory Start..."); return exchange -> { ServerHttpRequest request = exchange.
Python3 查找替换文件中的一行 hugo blog 里面的文章,统一修改时间,把最后秒和文件名最后两位同步。 代码片.
# -*- coding: utf-8 -*- import os import re def time_mod(file,second): if len(second)<2: second="0"+second f=open(file,'r',encoding='utf-8') n=open(file,'r+',encoding='utf-8') for line in f: if "date: 20" in line: line="date: 2022-03-01 09:54:"+second+'\n' n.write(line) f.close() n.close() path="D:\support\content\post" for file in os.listdir(path): file_path=os.path.join(path,file) if os.path.isdir(file_path): pass else: ext=file.split('.')[1] if ext=='md': name=file.split('.')[0] a=name.split('-') s=a[-1] time_mod(file_path,s)
1.生命周期 vue有八个生命周期,它们跟el、data、methods平级
分别是:
beforeCreate() 、create() 、beforeMount()、mounted()、beforeUpdate()、updated()、beforeDestroy()、destroyed()
2.axios Axios 是一个基于 Promise 的 HTTP 库,可以用在浏览器和 node.js 中。使用时需要链入axios的js文件。
它是需要写在vue八个生命周期中的created(){}里的,通过axios.get及axios.post请求数据
如图:
3.vue中的动画 1.在html中需要使用 transition 将需要过渡的元素包裹起来
如:
2.在css里需要定义类的样式:
入场动画: .fade-enter{}表示开始状态 、.fade-enter-active{}表示动画的过度、.fade-enter-to表示结束状态。
离场动画:.fade-leave{}表示开始状态 、.fade-leave-active{}表示动画的过度、.fade-leave-to表示结束状态。
如果没有在transition标签里添加name属性,那么入场动画和离场动画中的fade就用 v 来表示:.v-enter{},name的属性值自定义,只需要在设置动画样式时在 -enter或者-leave前边加上name的属性值即可。
使用第三方动画库: 第一步导入动画类库<link rel="stylesheet" type="text/css" href="./lib/animate.css">(这里用的是animate的动画类库)
第二步定义transition及属性:
使用动画钩子函数 v-for的列表过渡在定义DOM结构中需要使用transition-group 组件把v-for循环的列表包裹起来
如:
#include <stdio.h> int main () { int a; scanf("%d",&a); int i,j,k; int cnt =0; i = a; while( i<=a+3 ){ j = a; while( j<=a+3 ){ k = a; while( k<=a+3 ){ if ( i!=j ){ if( i!=k ){ if( j!=k ){ cnt++; printf("%d%d%d",i,j,k); //printf("%d", i*100+j*10+k); if ( cnt == 6 ){ printf("\n"); cnt = 0; }else{ printf(" "); } } } } k++; } j++; } i++; } return 0; } 水仙花数(SHD) #include <stdio.
int n; scanf("%d",&n); int fact = 1; int i = 1; while ( i <= n ){ fact *= i; i++; } printf("%d!=%d\n",n,fact); 用for循环表示:
for循环后大括号内三个条件(初始动作;循环继续的条件;循环每轮要做的动作)
int n; scanf("%d",&n); int fact = 1; int i = 1; for ( i=1; i<=n; i++ ){ fact *= i; } printf("%d!=%d\n",n,fact); 离开多重循环:
例子 凑硬币
#include <stdio.h> int main() { int x; int one,two,five; scanf("%d",&x); for( one = 1; one < x*10; one++){ for( two = 1; two < x*10/2; two++){ for( five = 1; five < x*10/5; five++){ if( one + two*2 + five*5 == x*10){ printf("
选项设定使sw更快捷
运行更快一点
鼠标笔式设定
常见快捷键使用
设计库使用
快速装配技巧
装配体——插入零部件——浏览——√:装配第一个零件要点左上的√号//各个基准面重合,方便以后装配。右键点击某个零件可以自己动快捷配合:按住Ctrl键点两个面,放开Ctrl键,点击跳出的框里面的配合。 同心圆:按住Alt键,拖着圆去另外一个圆,自动同心圆。复制:ctrl拖出角度:两个面,最大最小角度
最近发现联通的路由器可以设置FTP,用作家庭储存,在网上找了很久才找到有用的信息,这里发出来帮大家节省时间。
登录管理后台,登录管理员账号,默认密码:CUAdmin
打开FTP功能
在安全设置中勾选LAN/WLAN通过FTP访问
最后,插入U盘,在家庭储存中设置相应的FTP信息
想要用流对List<Integer>进行求和,但查找完资料都是对List<Object>中Object中的某个字段进行求和,就像这样:
long sum = list.stream().mapToLong(User::getAge).sum(); 而我list中本身存的就是基本类型的数字,并不适用。后来在IBM开发者社区中找答案:
long sum = list.stream().reduce(Integer::sum).orElse(0); 看来对流操作还是不太熟。
参考链接:
Java 8 中的 Streams API 详解
1.蓝桥杯 ----数学-----动态规划笔记
2.C++蓝桥杯基础知识常用整理
陆续更新中-------------------------------------------
目录
常用开始模板 int 和 string 的互转
数字字符串的转换位数方法 typedef的用法 哈希的简单运用
常用容器的输入输出
字符串中固定字符的数量
进制之间的转换
常用开始模板 #include<bits/stdc++.h>//万能头文件 using namespace std;//命名空间 typedef long long LL;//使用typedef关键字来定义自己习惯的数据类型名称 int main(){ return 0; } int 和 string 的互转 string 转 int:
这个最为常见 一般int num = stoi(s) 转为int 类型
还有long num = stol(s); long long num = stoll(s);
同理 想转换为浮点型 就有 double num = stod(s) float num = stof(s);
注意看 也就只有sto不变 后面的字母根据转换类型改变 还是很好记得
1、先全局安装prettier
npm i -g prettier
2、webstorm内设置如下
如图,设置里修改
如果改成utf-8还是乱码,可以改成其他编码格式试试
对象序列化流与反序列化流: Java对象是在Java虚拟机上生成的,如果需要远程传输或者保存在硬盘上,就要将java对象转换成可传输的文件流
作用:
把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中(持久化对象)
在Java中创建的java对象只有当Java虚拟机运行时才能存在,也就是这些对象的生命周期不会比JVM的生命周期更长。但在现实应用中,就可能要求在JVM停止运行之后能够保存指定的对象(持久化对象),并在将来重新读取被保存的对象。
在网络上传送对象的字节序列。(网络传输对象)
网络通信时,无论是何种类型的数据,都会转成字节序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象
序列化与反序列化: 序列化: 将Java对象转换为字节序列的过程
反序列化: 将字节序列转回java对象的过程
1.对象序列化流: 对象序列化流: ObjectOutputStream
将Java对象的原始数据类型和图形写入OutputStream。可以使用ObjectInputStream读取(重构)对象。可以通过使用流的文件来实现对象的持久存储。
如果流是网络套接字流,则可以在另一个主机上或另一个进程中重构对象
构造方法:
ObjectOutputStream(OutputStream out) //创建一个写入指定的OutputStream的ObjectOutputStream 序列化对象的方法:
void writeObject(Object obj) //将指定的对象写入ObjectOutputStream 注意:
一个对象要想被序列化,该对象所属的类必须必须实现Serializable接口,Serializable只是一个标记接口,实现该接口,不需要重写任何方法
import java.io.Serializable; public class Student implements Serializable { } 举个栗子:
将学生对象存储到文件中
首先我们定义一个学生类,类中有姓名和年龄两个成员变量,实现了Serializable接口
import java.io.Serializable; public class Student implements Serializable { private String name; private int age; //无参构造,带参构造自行脑补吧 } 然后在测试类中,创建学生对象写入文件
public static void main(String[] args) throws IOException { //创建一个写入指定的OutputStream的ObjectOutputStream ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("
Vue基础-模板语法 1.0 methods方法绑定this 问题一:不能使用箭头函数 问题二:this到底指向了什么? 2.0 模板语法 2.1 Mustache双大括号语法 2.2 V-once指令 2.3 v-text指令 2.4 v-html 2.5 v-pre 2.6 v-cloak 2.7 v-bind的绑定属性 2.8 绑定基本属性 2.9 绑定class介绍 2.10 绑定style介绍 2.11 绑定一个对象 2.12 v-on绑定事件 2.13 条件渲染 2.14 template元素 2.15 v-show和v-if的区别 2.16 列表渲染 v-for支持的类型
3.0 模板语法 3.1 数组更新检测 3.2 v-for中的key是什么用
千位分隔符格式的规则是数字的整数部分每三位一组,以“,”分节。小数部分不分节 。示例:19,351,235.235767 1.方法一 实现思路是将数字转换为字符数组,再循环整个数组, 每三位添加一个分隔逗号,最后再合并成字符串。因为分隔符在顺序上是从后往前添加的:比如 1234567添加后是1,234,567 而不是 123,456,7 ,所以方便起见可以先把数组倒序,添加完之后再倒序回来,就是正常的顺序了。要注意的是如果数字带小数的话,要把小数部分分开处理。
function numFormat(num){ num=num.toString().split("."); // 分隔小数点 var arr=num[0].split("").reverse(); // 转换成字符数组并且倒序排列 var res=[]; for(var i=0,len=arr.length;i<len;i++){ if(i%3===0&&i!==0){ res.push(","); // 添加分隔符 } res.push(arr[i]); } res.reverse(); // 再次倒序成为正确的顺序 if(num[1]){ // 如果有小数的话添加小数部分 res=res.join("").concat("."+num[1]); }else{ res=res.join(""); } return res; } var a=1234567894532; var b=673439.4542; console.log(numFormat(a)); // "1,234,567,894,532" console.log(numFormat(b)); // "673,439.4542" 2.方法二 使用JS自带的函数 toLocaleString
toLocaleString() 方法返回这个数字的字符串形式。
var a=1234567894532; var b=673439.4542; console.log(a.toLocaleString()); // "1,234,567,894,532" console.log(b.toLocaleString()); // "673,439.454" (小数部分四舍五入了) 3. 方法三 使用正则表达式和replace函数,相对前两种我更喜欢这种方法,虽然正则有点难以理解。replace 语法:str.
文章目录 一、Vue CLI是什么?二、用Vue CLI创建项目1、全局安装Vue CLI2、创建项目3、选择配置4、选择Vue的版本5、router是否使用history模式6、选择css预编译语言7、选择代码规范工具8、选择配置保存方式9、是否保存配置信息 三、运行项目 一、Vue CLI是什么? Vue CLI 是基于 webpack构建,并带有合理的默认配置; 可以通过项目内的配置文件进行配置; 可以通过插件进行扩展的一个基于 Vue.js 进行快速开发的完整系统。Vue CLI 致力于将 Vue 生态中的工具基础标准化。它确保各种构建工具能够基于智能的默认配置即可平稳衔接。
二、用Vue CLI创建项目 1、全局安装Vue CLI 因为npm是国外的源,下载速度比较慢,我换成了阿里的源,所以使用cnpm命令。
cnpm install -g @vue/cli 若安装成功,则输入vue --version,会有如图显示。
如果想要更新Vue CLI,重新安装即可(会覆盖以前的),这是最有效的方法。
2、创建项目 先cd进将要存放项目的文件夹,执行
vue create 项目名(项目名不能有大写字母) 会进入,按上下键移动可选择安装。
第一个是基于vue2的默认安装最低配置,第二个是基于vue3的默认安装最低配置,安装任意一个就能满足项目的基本需求,第三个是手动自行选择安装配置。
3、选择配置 只有你在上一步选择第三个才会有这一步,按上下键移动,按空格选中。
Choose Vue version选择vue版本Babel将ES6代码转为ES5代码TypeScript是否支持TypeScriptProgressive Web App (PWA) Support是否支持PWA(谷歌的离线应用)Router路由Vuex状态管理CSS Pre-processorscss预处理Linter / Formatter代码规范工具Unit Testing单元测试E2E Testing端对端测试 4、选择Vue的版本 是vue.js2还是vue.js3
5、router是否使用history模式 这里会询问你路由是否使用history模式,建议选择是。
6、选择css预编译语言 这里有两个Sass/Scss,其中dart-sass比node-sass效率更高,下载更方便。
7、选择代码规范工具 ESLint with error prevention only仅错误预防ESLint + Airbnb configESLint+Airbnb配置ESLint + Standard configESLint+标准配置ESLint + PrettierESLint+更漂亮的代码 选择安装 ESLint + Standard config
在这总结一下最近使用EndNote时遇到的一些小问题,相应的有一些设置的小技巧。
Q1:WORD文档中的参考文献如何导回EndNote? 有的时候想
1.在Word中,更新文件的引文信息
2.此时在EndNote 的library中会出现该文档的参考文献信息
3.直接选中所有文献,右键copy
4.粘贴到自己的新的分组中
(所链接的pdf也有的哦)
参考资料: 导出Word参考文献至EndNote并保留原Library的方法
Q2:怎么设定引文插入位置,而不是默认的文档末尾呢? 默认情况下,插入文献后是这样的:
顺便简单描述一下文献插入过程:
点击文档上面栏目里的EndNote ->
最左边有插入文献蓝,选择对应的插入形式。
如图:
效果是这样的:
如何让它显示在参考文献那里呢?
1.在EndNote中,点击Edit,选择 Output styles ,选择其中一种想要修改的引文模式
2.选择Sections,勾选第二栏,稍稍看一下它的说明,选择合适的模式
如下图:
3.在Word中找到插入分页和分节符
我发现我的 插入 选项卡中没有显示这一栏,于是就要自己去设置一下:
插入那里点击右键,选择 自定义功能区,然后找到插入分页和分节符,新建组,添加到右边,即可,之后就会有出现了,效果如下:
4.在参考文献四个字的后边插入 连续的分节符
效果如下:
Q3:如何设置文献引用的链接 如果文章很长,然后想看看参考文献具体内容,想用超链接能直接到文档末尾这种,该怎么操作呢?
1.在Word中点击EndNote选项
然后:
把那两个选项勾选上,下面那个勾上了就会有超链接的样式,有变颜色和添加下划线:
两个都勾选上的效果如下:
按Control 点击[1] 就能够自动滑倒相应的参考文献位置。
暂时记录这些啦!
对了,我的是EndNote X9,Word2019。
http://itmyhome.com/java-api/index.html?overview-summary.html
或者下面这个,包更全,但是解释没有上面这个解释的全
https://www.matools.com/api/java8
文章目录 VSCode中git使用vscode 拉取git仓库使用vscode提交代码vscode git提交代码忽略node_modules 推送本地文件(推送)package-lock.json不需要写进 .gitignore VSCode中git使用 vscode 拉取git仓库 直接选择克隆存储库,输入你的仓库地址,然后回车选择要存储的位置即可!
使用vscode提交代码 vscode git提交代码忽略node_modules 一、无 .gitignore 文件时,在项目文件右键,Git Bash 进入命令行
输入
touch .gitignore
生成gitignore文件
二、在文件.gitignore里输入
node_modules/ dist/ 此时git再上传时就忽略了node_modules和dist文件
推送本地文件(推送) vscode源代码管理器(git可视化操作)
参考URL: https://www.jianshu.com/p/ef0438a8b941
在VSCode中新增、删除或编辑相关文件,可在VSCode中的终端控制台执行以下命令,以便将文件暂存-提交到本地仓库,并推送到远程仓库。
git add . //暂存所有更改
git commit -m “第一次提交说明信息” //提交所有更改
git push -u origin main //推送到远程仓库
以上的操作,均可以在VSCode中通过“源代码管理器”完成。 上述第三条命令中使用“-u”选项,可以指定一个默认主机。即该条命令意思是:将本地仓库中的master分支推送到origin仓库中的master分支上,同时指定origin为默认主机,后面就可以不加任何参数使用git push了(推送)。
vscode源代码管理器(git可视化操作)
暂存到工作树
package-lock.json不需要写进 .gitignore package.json只能指定大版本的依赖包,例如安装·^vue 2.X.X,会安装大版本2的最新版本,^是大于等于当前版本且属于同一大版本2。
npm install可以生成package-lock.json文件,该文件应当提交到git上,用于其他开发人员拉取代码后安装相同版本的依赖包。
如果你查看当前项目某个依赖包的版本时,请在package-lock.json里看,千万不要到package.json上看,因为package.json上的版本是个初始化的版本(只是限定大版本号等)npm i不会更新package.json里依赖包的版本npm i xxx@2.6.1 -S 用这样的命令可以更新依赖包版本,并且改变package.json内的版本号如果想更新某个依赖包版本,可以使用如下命令 更新全局包:npm update -g
更新生产环境依赖包:npm update --save
粘包处理 对于JTT1078标准的终端视频流的输入,肯定有粘包,所以需要先进行粘包处理,大体就是将一个完整包拆解出来,使其他业务线程能够真正使用该完整包
消息头拆解 在粘包处理之后,针对单一的完整包,进行消息头的拆解,包括标志位、负载类型、包序号、SIM卡号、逻辑通道号、数据类型、时间戳以及消息体长度的信息,并缓存起来,
消息体处理 根据其sim卡号和逻辑通道号,可以确定该终端唯一通路的视频流信息(注意,此处如果跟历史回放视频同路的话,会造成无法正确识别是实时视频流,还是历史回放流,所以建议是另起一个监听端口,来接收历史回放流。
根据其数据类型,区分是音视频帧,还是视频帧。
如果是音频帧,则先判断处是aac、g711a还是adpcma,然后将他们统一转换为aac的格式,输入到视频服务系统中进行音频流的播放。
如果是视频帧,则从第一个包开始收集,集齐完整的一帧数据后,输送到视频服务系统中。
然后由视频服务系统对音视频流进行转换,转换成所需要的如rtsp、rtmp、http-flv等格式,供视频客户端进行播放调用。
(欢迎交流)
声明:本篇博客的主要目的是对STM32F4系列单片机ADC外设的要点和疑难点进行总结整理(因为手册内容太多,容易眼花缭乱,抓不住重点),并且尽量避免成为手册的搬运工(否则还不如直接去看手册)。同时在博客的最后,会附上一些ADC常用功能的示例Demo (会随着时间不断完善添加)。
1 概述 (概述内容摘自手册)
1.1 ADC简介 12 位 ADC 是逐次趋近型模数转换器。它具有多达 19 个复用通道,可测量来自 16 个外部源、两个内部源和 VBAT 通道的信号。这些通道的 A/D 转换可在单次、连续、扫描或不连续采样模式下进行。ADC 的结果存储在一个左对齐或右对齐的 16 位数据寄存器中。ADC 具有模拟看门狗特性,允许应用检测输入电压是否超过了用户自定义的阈值上限或下限。
1.2 ADC主要特性 可配置 12 位、10 位、8 位或 6 位分辨率 在转换结束、注入转换结束以及发生模拟看门狗或溢出事件时产生中断 单次和连续转换模式 用于自动将通道 0 转换为通道“n”的扫描模式 数据对齐以保持内置数据一致性 可独立设置各通道采样时间 外部触发器选项,可为规则转换和注入转换配置极性 不连续采样模式 双重/三重模式(具有 2 个或更多 ADC 的器件提供) 双重/三重 ADC 模式下可配置的 DMA 数据存储 双重/三重交替模式下可配置的转换间延迟 ADC 电源要求:全速运行时为 2.4 V 到 3.6 V,慢速运行时为 1.8 V ADC 输入范围:规则通道转换期间可产生 DMA 请求 2 ADC框图 框图说明:
①处,是 ADC 的供电电源()和参考电源()。为了提高转换的精确度,ADC使用一个独立的电源供电,过滤和屏蔽来自印刷电路板上的毛刺干扰;ADC的电源引脚为VDDA,电源地为VSSA,如果有VREF- 引脚(根据封装而定),它必须连接到VSSA,确保共地。ADC的参考电压都是通过Vref+提供的。100脚以上的型号,Vref+引到了片外,引脚名称为Vref+;64脚和小于64脚的型号,Vref+在芯片内部与VCC信号线相连,没有引到片外,这样AD的参考电压就是VCC上的电压。VDDA和VREF的电压范围请查阅手册。②处,ADC的输入通道,F4系列单片机ADC共有19个通道,其中外部的16个通道就是框图中的ADCx_IN0到ADCx_IN15,这16个通道对应着不同的IO口,具体对应关系可以在手册或者CUBEMX配置界面获得。另外三个内部通道连接温度传感器、内部电压和电池电压。F4系列的不同型号略有差异,需要查阅手册确定。③处,STM32F4将ADC的转换分为2类通道:规则通道和注入通道。规则通道相当于正常运行的程序,而注入通道,就相当于中断。注入通道的转换可以打断规则通道的转换,在注入通道被转换完成之后,规则通道才得以继续转换。规则通道组最多包含16个通道,而注入通道组最多包含4个通道。④处,是 ADC 的触发源,ADC转换可以由控制寄存器ADC_CR2的位ADON来启动,也可以由外部事件的触发来启动转换。使用控制寄存器启动时,很简单,写1开始转换;写0停止转换。使用外部事件来触发转换,这个触发包括内部定时器触发和外部IO触发。触发源的选择由ADC_CR2的EXTSEL[2:0]和JEXTSEL[2:0]位来控制,EXTSEL[2:0]用于规则通道的触发源,JEXTSEL[2:0]用于选择注入通道的触发源。如果使能了外部触发事件,我们还可以通过设置ADC控制寄存器2:ADC_CR2的EXTEN[1:0]和JEXTEN[1:0]来控制触发极性,可以有4种状态:禁止触发检测、上升沿检测、下降沿检测以及上升沿和下降沿均检测。⑤处,ADC的时钟源来源于ADC预分频器,是由PCLK2经过ADC Prescaler 得到。最大为36MHz,通常设置为21MHz。分频因子由ADC通用寄存器ADC_CCR的ADCPRE[1:0]设置,可设置的分频系数有2、4、6和8。⑥处,当ADC转换完成后,根据转换组的不同,规则组的数据放在ADC_DR寄存器,注入组的数据放在JDRx寄存器。如果使用双重或者三重模式那规则组数据是存放在通用寄存器ADC_CDR内的。规则通道有16个,规则寄存器只有一个,如果使用多通道转换,那转换的数据就全都挤在了DR里面,前一个时间点转换的通道数据,就会被下一个时间点的另外一个通道转换的数据覆盖掉,所以当通道转换完成后就应该吧数据取走。或者开启DMA模式,将数据传输到内存里面,常用的方法是开启DMA传输。注入组有4个通道,相应的寄存器也有4个,这个不会有数据覆盖问题。⑦处,数据转换结束后,可以产生中断,中断分为四种:规则通道转换结束中断、注入转换通道转换结束中断、模拟看门狗和溢出中断。模拟看门狗中断:当ADC转换的模拟电压低于阈值或者高于阈值时,就会产生中断,前提是我们开启了模拟看门狗中断。溢出中断:如果DMA传输数据丢失,会置位ADC状态寄存器ADC_SR和OVR位,如果同时使能了溢出中断,那在转换结束后会产生一个溢出中断。规则和注入通道转换结束后,除了产生中断,还可以产生DMA请求,将转换好的数据直接存储在内存里面。 3 功能说明 3.
应用场景 hive表有很多列,大部分列需要,其中一列不需要,例如分区表的dt字段不要,例如1000列中去掉1列
实现方法 1. 方法 hive sql: 实现功能 select `(dt)?+.+` from test; 这里dt是不要的字段。
以上sql生效需要设置一个参数:
set hive.support.quoted.identifiers=none;
2.demo测试 让语法生效
hive> set hive.support.quoted.identifiers=none; hive> set hive.cli.print.header; hive.cli.print.header=false hive> set hive.cli.print.header=true; 表全部字段
hive> select * from test; hook status=true,operation=QUERY OK name friends children address songsong ["bingbing","lili"] {"xiao song":18,"xiaoxiao song":19} {"street":"hui long guan","city":"beijing"} yangyang ["caicai","susu"] {"xiao yang":18,"xiaoxiao yang":19} {"street":"chao yang","city":"beijing"} Time taken: 0.14 seconds, Fetched: 2 row(s) 从select * 中去掉一个字段address
hive> select `(address)?+.+` from test; hook status=true,operation=QUERY OK name friends children songsong ["
文章目录 迭代介绍可迭代对象迭代器对象迭代器对象取值 方法的简写for循环内部原理异常处理异常的分类异常的类型异常的处理try/except 语句try/except...else 语句try/except...finally 语句try/except.../else/finally 语句 断言主动报错 for 循环的本质迭代取值与索引取值的对比 迭代介绍 什么叫做迭代,迭代可以理解为更新换代,每一次迭代的过程都需要依赖于上一次的结果。迭代器有两个基本的方法:iter()和 next()
while True: print(666) 像这种单纯的循环并不能称之为迭代,因为它没有和上一次的结果有关系。 list_a = ['XWeXiang', 123] i = 0 while i < len(list_a): print(666) i += 1 这种属于迭代,但是并没有取值。 list_a = ['XWeXiang', 123] i = 0 while i < len(list_a): print(list_a[i]) i += 1 此时可以迭代列表中的元素并取出。 可迭代对象 什么是可迭代对象?如果某一个对象中有着内置方法 __iter__ 的称之为可迭代对象 这个方法读作双下iter方法。 如何判断一个对象是否为可迭代的对象
方式一 通过 dir() 函数来判断该对象是否有 __iter__ 方法 print(dir(list_a)) 方式二 直接在该对象加点就能弹出它能用的方法,相对于方式一更简单。 哪些是可迭代的对象
通过上面的方法我们可以得到可迭代的对象类型有:字符串、列表、字典、元组、集合、文件 我们可以发现这些都支持 for 循环,其实是因为它们是可迭代对象才支持 for 循环。 迭代器对象 迭代器
查看Linux服务器内存情况 一、free命令二、top命令总结 一、free命令 free命令用于显示内存的使用情况,包括实体内存,虚拟的交换文件内存,共享内存区段,以及系统核心使用的缓冲区等。
语法:
free [-bkmotV][-s <间隔秒数>] 如下图:
free -h会以合适的单位显示内存情况,-b、-k、-m、-g分别以Byte、KB、MB、GB为单位显示,如下只展示free -h的情况
二、top命令 top命令可以查看各个进程的情况,而free命令是服务器整体情况
直接输入top命令如下图
进入top的实时界面后,默认按照CPU的使用率排序,通过“shift+m”按键将进程按照内存使用情况排序,
因本篇讲的是查看内存情况,top命令只写内存情况,如图,其中
RES: 常驻内存,是进程切实使用的物理内存量,free命令中看到的used列下面的值,就包括常驻内存的加总,但不是虚拟内存的加总;
%MEM:占用内存百分比。
总结 以上就是两种查看Linux服务器内存情况的方法。
Dubbo invoke 报这个错误No such method,当你在ls命令下,这个方法实际上是存在的,主要问题就是json参数前面需要添加一个class的参数头,这个具体的参数实体,其实就是你对应api的参数实体的包位置
读音 发音就是Time leaf
有些培训的会念成塞姆来福
其实念啥没问题
定义 Thymeleaf 是一个模板引擎,由于SpringBoot默认使用Thymeleaf,现逐步取代jsp。
特点 动静结合:Thymeleaf 在有网络和无网络的环境下皆可运行,无网络显示静态内容,有网络用后台得到数据替换静态内容。支持 html 原型,浏览器解释 html 时会忽略未定义的标签属性,所以 thymeleaf 的模板可以静态地运行;当有数据返回到页面时,Thymeleaf 标签会动态地替换掉静态内容,使页面动态显示。
与SpringBoot完美整合,springboot默认整合thymeleaf。提供spring标准方言和一个与 SpringMVC 完美集成的可选模块,可以快速的实现表单绑定、属性编辑器、国际化等功能。
链接 官网
官方文档
依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> 使用方式 绑定 把html等文件放在resources的templates下。
在controller文件中写导向
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>测试</title> </head> <body> <h1>test?</h1> </body> </html> package com.example.demo.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @Controller //templates下的页面需要通过controller进行跳转,使用thymeleaf public class IndexController { @GetMapping("test") public String test(){ return "test"; } } 传值 @Controller //templates下的页面需要通过controller进行跳转,使用thymeleaf public class IndexController { @GetMapping("
1、说明你的组件名不是多个单词组成的,你要把组件改成多个单词,将Login改成LoginView。
2、或者可以禁用vue的严格模式。
在项目根目录下的vue.config.js文件中
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave: false //加上这个配置
})
效果图: 代码优化/简化、教科书级别注释、复制粘贴即可用
代码: package com.zistone.factorytest0718.view; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.RectF; import android.util.AttributeSet; import android.util.Log; import android.view.View; import com.zistone.factorytest0718.BaseActivity; /** * 圆形进度条控件 * * @author LiWei * @date 2021/2/19 16:17 * @email 652276536@qq.com */ public class MyCircleProgress extends View { private static final String TAG = "MyCircleProgress"; private Paint _paint; private RectF _rectF; private Rect _rect; private int _current = 1, _max = 100; //圆弧(也可以说是圆环)的宽度 private float _arcWidth = 30; //控件的宽度 private float _width; public MyCircleProgress(Context context) { this(context, null); } public MyCircleProgress(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MyCircleProgress(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); _paint = new Paint(); _paint.
这个参数出现在一些地方,例如:
nn.Embedding、nn.Embedding.from_pretrained。
import torch import torch.nn as nn import torch.optim as optim 参数含义 如下:
padding_idx (int, optional) – If specified, the entries at padding_idx do not contribute to the gradient; therefore, the embedding vector at padding_idx is not updated during training, i.e. it remains as a fixed “pad”. For a newly constructed Embedding, the embedding vector at padding_idx will default to all zeros, but can be updated to another value to be used as the padding vector.
第一套 1.Java网络程序设计中,下列正确的描述是()
正确答案: A D
Java网络编程API建立在Socket基础之上
Java网络接口只支持tcP以及其上层协议
Java网络接口只支持UDP以及其上层协议
Java网络接口支持IP以上的所有高层协议
2.以下哪些类是线程安全的()
正确答案: A D E
Vector
HashMap
ArrayList
StringBuffer
Properties
A,Vector相当于一个线程安全的List
B,HashMap是非线程安全的,其对应的线程安全类是HashTable
C,Arraylist是非线程安全的,其对应的线程安全类是Vector
D,StringBuffer是线程安全的,相当于一个线程安全的StringBuilder
E,Properties实现了Map接口,是线程安全的
第二套 下面有关jdbc statement的说法错误的是?
正确答案: C
JDBC提供了Statement、PreparedStatement 和 CallableStatement三种方式来执行查询语句,其中 Statement 用于通用查询, PreparedStatement 用于执行参数化查询,而 CallableStatement则是用于存储过程
对于PreparedStatement来说,数据库可以使用已经编译过及定义好的执行计划,由于 PreparedStatement 对象已预编译过,所以其执行速度要快于 Statement 对象”
PreparedStatement中,“?” 叫做占位符,一个占位符可以有一个或者多个值
PreparedStatement可以阻止常见的SQL注入式攻击
征程头像征程
1.Statement、PreparedStatement和CallableStatement都是接口(interface)。
2.Statement继承自Wrapper、PreparedStatement继承自Statement、CallableStatement继承自PreparedStatement。
3.
Statement接口提供了执行语句和获取结果的基本方法;
PreparedStatement接口添加了处理 IN 参数的方法;
CallableStatement接口添加了处理 OUT 参数的方法。
4.
a.Statement:
普通的不带参的查询SQL;支持批量更新,批量删除;
b.PreparedStatement:
可变参数的SQL,编译一次,执行多次,效率高;
安全性好,有效防止Sql注入等问题;
支持批量更新,批量删除;
c.CallableStatement:
继承自PreparedStatement,支持带参数的SQL操作;
支持调用存储过程,提供了对输出和输入/输出参数(INOUT)的支持;
Statement每次执行sql语句,数据库都要执行sql语句的编译 ,
最好用于仅执行一次查询并返回结果的情形,效率高于PreparedStatement。
有时候我们搭建了一个mysql服务器,开始给root设置了密码,但是一时忘记保存了,第二天忘记密码,那忘记了密码怎么办呢?不要着急,待J哥慢慢给你说来~~~~ linux服务器
mysql安装包
[root@LaityPyhon ~]# service mysqld stop 先把mysql停止
[root@LaityPyhon ~]# mysqld_safe --skip-grant-tables & 安全模式进入mysql,并且跳过授权表
[root@LaityPyhon ~]# mysql -uroot -p 输入 mysql -uroot -p 不要敲密码,回车进入即可
mysql> use mysql mysql> update user set password=PASSWORD("123456")where user="root"; mysql> flush privileges; mysql> quit 使用一下mysql这个库就好,然后执行一下update语句(括号里面的是你要修改的新密码),然后刷新一下授权表,最后退出即可。
[root@LaityPyhon ~]# service mysqld restart [root@LaityPyhon ~]# mysql -uroot -p 将mysql重启,然后敲密码123456进入就好了。
目录
GO语言的几种循环
for循环
练习,求1-10得和
For-each range循环
for循环嵌套
练习1:输出2-100之间的质数
练习2:输出九九乘法表
break语句
break标记使用
continue语句
continue 标签
goto语句
总结
GO语言的几种循环 在不少实际问题中有许多具有规律性的重复操作,因此在程序中就需要重复执行某些语句。
以下几种类型循环处理语句:
循环类型描述[for循环]描述重复执行语句块[循环嵌套]在for循环中嵌套—个或多个for循环 循环控制语句
循环控制语句可以控制循环体内语句的执行过程。
以下几种循环控制语句:
控制语句描述[break语句]经常用于中断当前for循环或跳出switch语句[continue语句]前循环的剩余语句然后继续进行下一轮循环[goto语句]将控制转移到被标记的语句 无限循环
如果循环中条件语句永远不为false则会进行无限循环,可以通过 for循环语句中只设置一个条件表达式来执行无限循环:
例如:
package main import( "fmt" "time" ) func main() { i : = 0 for true{ fmt . Printf("%d\n", i) i++ time.sleep(time . Second) for循环 for循环是一个循环控制结构,可以执行指定次数的循环。
for 循环有3种形式,只有其中的一种使用分号。
和C语言的for一样:
for init; condition; post {} 和C的while一样:
for condition { } 和C的 for(;;)一样;
for { } init:一般为赋值表达式,给控制变量赋初值; ·
性能强:iTOP-3568开发板采用瑞芯微RK3568处理器,是一款中高端通用型SOC,22nm工艺制程。内部集成了四核64位Cortex-A55处理器。主频高达2.0Ghz,2GB内存,16GB EMMC,RK809动态调频。
双核心架构GPU:集成了双核心架构GPU、ARM G52 2EE、支持OpenGL ES1.1/2.0/3.2、OpenCL2.0、Vulkan1.1、内嵌高性能2D加速硬件。
内置独立NPU:内置独立NPU,算力达0.8T,可用于轻量级人工智能应用。
强大的视频编解码:高性能VPU支持4K 60帧视频解码,多路视频源同事解码。H.265/H.264/VP8视频解码和1080P 100fps H.265/H.264/VP9视频编码。
接口丰富:双路千兆以太网、SATA3.0、PCIE3.0、MIPI、HDMI、MIPI、CAMERA、4G等接口一应俱全。
系统支持:流畅运行Android11,Buildroot+QT,Yocto,Debian10系统,新增Ubuntu20系统。
全新升级《开发板使用手册》迅为工程师编写了更加专业丰富的教程。我们从熟悉硬件平台,到软件开发坏境搭建,再到源码编译,镜像烧写,系统调试技巧,Android系统开发,Android应用开发,Linux系统开发,QT应用开发,编写进开发使用手册,提升研发速度。
通过电磁兼容、电磁辐射标准检测、安规检测、高低温坏境检测,7*24小时长期稳定运行。
主要面向物联网网关、NVR存储、工控平板、工业检测、工控盒、卡拉OK、云终端、车载中控等行业定制市场。
一、概述
date代表一个特定的时间,精确到毫秒
二、构造方法
方法名说明public Date()分配一个Date对象,并初始化,以便它代表被分配的时间,精确到毫秒public Date(long date)分配一个Date对象,并将其初始化为表示从标准基准时间起指定的毫秒数 import java.util.Date; public class DateDemo{ public static void main(String []args){ //创建Date对象使用无参构造 Date d=new Date(); System.out.println(d);//调用无参构造直接输出显示与计算机时钟时间相同的时间,因为重写了toString方法 System.out.println("----------------------------------------------------------") long date=1000*60*60;//从毫秒转化为小时的单位换算 Date d1=new Date(date); System.out.println(d1);//此调用会输出1970年0时0点之后加上一个小时的时间,换算CST后应再加8个小时的时区差 } } 三、Date类的常用方法
方法名说明public long getTime()获取的是日期对象从1970年一月一日00:00:00到目前的毫秒数public long setTime(long time)设置时间,给的是毫秒值 四、SimpleDateFormat类
1.概述:SimpleDateFormat是一个具体的类,用于区域设置敏感的方式格式化和解析日期
2.构造方法
方法名说明public SimpleDateFormat()构造一个SimpleDateFormat,使用默认模式和日期格式public SimpleDateFormat(String pattern)构造一个SimpleDateFormat使用给定的模式和默认的日期格式 3.SimpleDateFormat格式化与解析日期
格式化(从Date到String)
public final String format(Date date):将日期格式化成日期/时间字符串
import java.util.Date; public class DateDemo{ public static void main(String []args){ //创建对象,格式化(从Date到String) Date d=new Date(); SimpleDateFormat sdf=new SimpleDateFormat();//也可以使用带参构造加上自己的年月日格式 String s=sdf.
OWASP top10 2021年版TOP 10产生三个新类别,且进行了一些整合
考虑到应关注根本原因而不是症状。
A01:失效的访问控制 从第五位上升称为Web应用程序安全风险最严重的类别,常见的CWE包括:将敏感信息泄露给未经授权的参与者、通过发送的数据泄露敏感信息、跨站请求伪造(csrf)
风险说明: 访问强制实施策略,使用户无法在其预期权限之外操作。失败的访问控制通常导致未经授权的信息泄露,修改或者销毁所有数据,或在用户权限之外执行业务功能。
常见的访问控制脆弱点:
违法最小权限原则或默认拒绝原则,即访问权限应只授予特定能力、角色或用户,但实际上任何人都可以访问通过修改URL(参数修改或强制浏览),内部应用程序状态或者HTML页面,或者使用修改API请求的攻击工具绕过访问控制检查通过提供唯一的标识符允许查看或编辑他人账户API没有对POST、PUT和DELETE强制执行访问控制特权提升,在未登陆的情况下假扮用户或以用户身份登入时充当管理员 …
预防措施 开发人员和QA人员应进行访问控制功能的单元测试和集成测试
访问控制只在受信服务器端代码或者无服务器API中有效,这样攻击者才无法修改访问控制检查或元数据
除公有资源外,默认访问拒绝
使用一次性的访问控制机制,并在整个应用程序中不断重用它们,包括最小化跨资源共享(CORS)的使用
建立访问控制模型以强制执行所有权记录,而不是简单接受用户创建、读取、更新或删除的任何记录
在日志中记录失败的访问控制,并在适当时向管理员告警(例如:重复故障)
…
A02:加密机制失效 上升一位到第二位,以前称为“敏感数据泄露”。敏感数据泄露更像是一种常见的表象问题而不是根本原因,这项风险重点是与加密机制相关的故障(或缺乏加密机制)
风险说明 首先要确认:对传输中的数据和存储数据都有哪些保护需求。例如:密码、信用卡号、医疗记录、个人信息和商业秘密需要额外保护。
对于数据,要确认:
在传输数据过程中是否使用明文传输?这和传输协议有关:HTTP、SMTP、经过TLS升级的FTP。外部网络流量是有害的,需要验证所有的内部通信
无论是在默认情况还是在旧的代码中,是否还在使用任何旧或者脆弱的加密算法或传输协议
是否默认使用加密密钥、生成或重复使用脆弱的加密密钥,或者是否缺少适当的密钥管理或密钥回转
接收到的服务器证书和信任链是否经过正确验证
…
预防措施 对应用程序处理、存储或者传输的数据分类,并根据相关要求确认哪些数据敏感对于没有必要存储的敏感数据,应当尽快清除确保加密存储所有的敏感数据确保使用了最新的,强大的标准算法、协议和密钥,并且密钥管理到位禁用缓存对包含敏感数据的响应不要使用传统协议HTTP、FTP等来传输敏感数据 …
A03:注入 注入降至第三,常见的CWE:跨站点脚本、SQL注入、文件名或路径的外部控制
风险说明 源代码审查是检查应用程序是否易受注入攻击的最佳方法。
强烈鼓励针对所有参数、标题、URL、cookie、JSON、SOAP和XML数据输入的自动测试
风险产生情况:
应用程序不会验证、过滤或清洗用户提供的数据动态查询或无上下文感知转义的非参数化调用之间在解释器中使用恶意数据被直接使用或连接。SQL或命令包含动态查询、命令或存储过程中的结构和恶意数据 预防措施 防止注入需要将数据与命令和查询分开:
推荐的选择是使用安全的API使用肯定或者白名单服务器端输入验证对于任何残余的动态查询,使用该解释器的特定转义语法转义特殊字符在查询中使用LIMIT和其他SQL控件,以防止在SQL注入的情况下大量披露记录 A04:不安全设计 这是2021的一个新类别,侧重于设计和体系结构缺陷相关的风险,呼吁更多的使用威胁建模、安全设计模式和参考体系结构
风险说明 不安全设计和不安全实现直接存在差异,我们区别设计缺陷和实现缺陷是有原因的,安全设计仍然可能存在实现缺陷,从而导致可能被利用的漏洞。
一个不安全设计不能通过一个完美的实现来修复。
预防措施 与应用安全专业人员建立并使用安全的开发生命周期,以帮助评估和设计与安全和隐私相关的控制
限制用户或服务的资源消耗
通过设计咋所有层中严格隔离租户
根据暴露和保护需要,对系统层和网络层进行分层
…
A05:安全配置错误 从上一版的第六名提升,90%都进行了某种形式的配置错误测试。
风险说明 缺少一个体系的、可重复的应用程序安全配置过程,系统将处于高风险中
你的应用程序可能受到攻击,如果应用程序是:
应用程序栈的任何部分缺少适当的安全加固,或者云服务的权限配置错误
应用程序启用或安装了不必要的功能(例如:不必要的端口、服务、网页、账户或权限)
默认账户和密码仍然可用且没有更改
目录
文字概念:
进程创建:
进程等待,处理僵尸进程:waitpid()
程序替换:
编写minishell程序了解进程替换: 文字概念: 操作系统:对计算机软硬件资源进行管理的软件
系统调用:操作系统向用户提供的用于访问内核的接口.
程序:程序就是程序员写的代码,指令集.
进程:操作系统的角度进程就是进程控制块pcb,在linux下是task_struct结构体.
进程控制块pcb:程序运行的动态描述,包含程序运行的各项信息 如标识符pid,内存指针,程序计数器, 上下文数据,进程状态,进程优先级,io信息,记账信息等.
进程状态:就绪,运行,阻塞三大类.
linux下分为 : 运行态 -R:正在运行的,以及拿到时间片就能运行的.
可中断休眠态 -S:可以被打断的阻塞状态.
不可中断休眠态 -D:顾名思义.
停止态 -T:停止运行.
僵尸态 -Z : 程序退出后等待父处理的状态 . 僵尸进程就是僵尸态的进程,退出后资源没有完全被释放的进程,是因为子进程先于父进程退出,为了保存自己的退出的返回值等待父进程处理返回值,等待过程就没完全释放资源.
避免方法:由于僵尸进程会导致资源泄漏我们要尽量避免产生僵尸进程进程等待,wait,waitpid方法.
处理 : 退出父进程,kill命令对僵尸进程没用.(kill pid)
演示:
孤儿进程: 父进程先于子进程退出,子进程就变成了孤儿进程,1号进程成为子进程的父进程.
孤儿进程不占据当前程序运行的会话,在后台运行(当前会话能打指令)
1号进程(init)是负责任的进程,所以孤儿进程退出不会成为僵尸进程,可以被kill掉
孤儿进程设置了自己的会话空间后成为守护进程(精灵进程),会话空间是问号"?",脱离了终端运行.
演示:
查看进程信息的指令:ps -ef或ps -aux,通常配合grep使用:ps -ef | grep "string" , 查找相关进程信息
创建进程: pid_t fork(),通过复制父进程创建一个新的进程(即子进程),无参. 如果是父进程则父进程得到的返回值是子进程的pid,是子进程则为0,创建失败返回-1. 在调用fork后的子进程,父进程代码和数据一模一样. 通过返回值在代码中对父进程子进程要运行的代码分流.fork后子进程版留了父进程的环境变量和当前工作目录. fork创建子进程在内核中通过调用clone实现. 具有写实拷贝机制!子进程创建后有自己的虚拟地址空间,与父进程映射同一块物理内存,但是,如果内存中数据发生改变(父进程修改或子进程修改),则为子进程针对这 一要修改的内存另开辟空间拷贝数据过去.
相关题目:
环境变量:保存程序运行环境参数等待变量,在进程之间传递数据(特性)
env:查看所有环境变量 set:查看环境中所有变量 echo:打印指令变量的数据.
export:设置环境变量. unset:删除环境变量. shell中默认环境变量存放在~/.bash_profile中.
1. Cascader级联选择器
1.1. 当一个数据集合有清晰的层级结构时, 可通过级联选择器逐级查看并选择。
1.2. Cascader属性
参数
说明
类型
可选值
默认值
value / v-model
选中项绑定值
无
无
无
options
可选项数据源, 键名可通过Props属性配置
array
无
无
props
配置选项, 具体见下表
object
无
无
size
尺寸
string
medium / small / mini
无
placeholder
输入框占位文本
string
无
请选择
disabled
是否禁用
boolean
无
false
clearable
是否支持清空选项
boolean
无
false
show-all-levels
输入框中是否显示选中值的完整路径
boolean
无
true
collapse-tags
多选模式下是否折叠Tag
boolean
无
false
separator
选项分隔符
string
无
迷宫生成算法是游戏中各种随机生成都可能用到的最基本的算法。下图展示了一个随机场景生成器的迷宫生成部分。
依次经过了6个步骤:生成迷宫=》调节占空比=》自动手绘效果=》平滑=》腐蚀=》移除死胡同.
首先生成迷宫,比较有名的是prim算法,可以生成主路扭曲型 和自然分岔型迷宫。
主路扭曲型迷宫一般分岔较少,有一条明显的主干道,适合于闯关游戏。
自然分岔型迷宫则分岔较多,没有明显的主路,比较适合于rpg类游戏。
prim算法生成的迷宫有一个特点,所有的路和墙都只有一个格子的宽度,通常不适合直接用于游戏中,需要做一系列的后期处理。
调节占空比:将墙和路随机拓宽 结合寻路算法拓宽主路:
添加手绘效果:
添加房间及斜向移动:
其它 迷宫生成算法
随机筑线法:先将整个地图初始化为路,然后随机筑一些线墙
噪声阈值法:先生成平滑的噪声图,噪声值小于阈值的地方挖出路径。
tsp、mst算法:利用巡回销售员算法 或最小路径树算法开挖路径。这是一个效果相当不错的算法,当然也可以使用只能直角拐弯的tsp、mst算法。
递归分割算法 圆形迷宫:
3d迷宫:
截图见下一篇文章
横版迷宫
迷宫算法在地形生成中的运用:
迷宫生成 :
//======================================================== // @Date: 2016.05 // @File: Include/Render/Maze.h // @Brief: Maze // @Author: LouLei // @Email: twopointfive@163.com // @Copyright (Crapell) - All Rights Reserved //======================================================== #pragma once #ifndef __Maze__H__ #define __Maze__H__ #include "Math/MathLib.h" #include "Texture.h" enum MazeMethod { LoadFromFile_, //随机筑路法 persent=road密度 RandRoad, //随机筑墙法 persent=wall密度 RandWall, //!
while循环 while语句也称判断语句
执行流程: a:执行初始化条件语句; b:执行判断条件语句,看其返回值是true还是false 如果是true,就继续执行 如果是false,就结束循环 c:执行循环体语句; d:执行控制条件语句 e:回到b继续。
语法如下。
while(条件表达式){
语句序列}
例如:计算1~1000的相加结果
结果如下
do...while循环 do...while循环与while相类似,区别在于while先判断再执行,do...while在于先执行再判断。
执行流程: a:执行初始化条件语句; b:执行循环体语句; c:执行控制条件语句; d:执行判断条件语句,看其返回值是true还是false 如果是true,就继续执行 如果是false,就结束循环 e:回到b继续。
语法如下:
do{
语句序列
}whlie(条件表达式);
for循环 执行流程: a:执行初始化表达式语句 b:执行判断条件语句,看其返回值是true还是false 如果是true,就继续执行 如果是false,就结束循环 c:执行循环体语句; d:执行控制条件语句 e:回到b继续。
语法如下:
for(初始化表达式语句;判断条件语句;控制条件语句) { 循环体语句; }
例如;用for循环计算1~100所有奇数之和。
运行结果如下:
它们的区别 区别:(1):do...while循环至少执行一次循环体。 而for,while循环必须先判断条件是否成立,然后决定是否执行循环体语句。
(2):A: 如果你想在循环结束后,继续使用控制条件的那个变量,用while循环,否则用for循环。不知道用for循环。 因为变量及早的从内存中消失,可以提高内存的使用效率。 B:建议优先考虑for循环,然后是while循环 ,最后是do...while循环
1. pdm 的两种项目 正常情况下,我们都是使用 pdm init 来初始化项目时,而初始化后,会在本地生成一个 pyproject.toml 文件和 pypackages 目录,这只是 pdm 默认的模式。
为理解方便,pdm 管理的项目,我将其分为两种
全局项目局部项目 实际上,咱在初始化的时候,还可以再加个参数 -g/–global ,它表示该项目将使用全局的 pdm 的 pyproject.toml 配置文件。
若你是首次使用 -g/–global 参数,那么它将创建 ~/.pdm/global-project/ 目录,将在该目录下创建 pyproject.toml
若你是二次使用 -g/–global 参数,那么你输入的信息将覆盖原来的 pyproject.toml 的配置
使用过 -g 后,你再使用 pdm list -g 查看全局已安装的包时,就会发现多了个 global-project 的包?然后在 Location 列有 -e /Users/iswbm/.pdm/global-project 指定全局模式 pyproject.toml 及 pdm.lock 所在的位置
默认情况下,当你没有指定 -g 参数去执行 pdm 命令时,它只会先从本地目录读取 pyproject.toml
而当你指定 -g 命令,不管你本地项目是否为一个 pdm 创建的项目,是否存在 pyproject.toml,pdm 都只会去读取全局的 pyproject.toml
如下所示,我分别在全局和本地的 pyproject.toml 添加不同的 shell 命令,在加 -g 和 不加 -g 的效果就非常明显了
一、三次多项式轨迹规划的缺陷 上一篇文章说道,三次多项式轨迹规划只能够保证速度和位移连续,并不能保证加速度连续。加速度不连续将会对使电机抖动、甚至冲击。
二、轨迹规划中的五次多项式 我们对加速度数值进行指定,将会增加两个加速度方程,总计6个方程组。他们分别是:
起末位移方程组起末速度方程组起末加速度方程组
x ( t ) = c 0 + c 1 t + c 2 t 2 + c 3 t 3 + c 4 t 4 + c 5 t 5 v ( t ) = c 1 + 2 c 2 t + 3 c 3 t 2 + 4 c 4 t 3 + 5 c 5 t 4 a ( t ) = 2 c 2 + 6 c 3 t + 12 c 4 t 2 + 20 c 5 t 3 (1) \begin{aligned} & x(t)=c_0+c_1t+c_2t^2+c_3t^3+c_4t^4+c_5t^5\\ & v(t)=c_1+2c_2t+3c_3t^2+4c_4t^3+5c_5t^4\\ & a(t)=2c_2+6c_3t+12c_4t^2+20c_5t^3 \end{aligned} \tag{1} x(t)=c0+c1t+c2t2+c3t3+c4t4+c5t5v(t)=c1+2c2t+3c3t2+4c4t3+5c5t4a(t)=2c2+6c3t+12c4t2+20c5t3(1)
类的简介: 一个源文件*.java必须与该文件中的主类同名(public class),源文件中有且只有一个主类。-->主方法main-存在与主类中;一个源文件中可以存在N个普通类,直接使用。
类中常量:static、final同时修饰,此时常量全局唯一且不可修改,所有对象共享此常量
阿里编码规约:类中如无特殊说明,所有成员变量统一使用private 封装(99%)
1.属性 属性 = 成员变量 = field = 域、字段
属性 VS 局部变量 1.相同点:
1.1 定义变量的格式:数据类型 变量名 = 变量值
1.2 先声明,后使用
1.3 变量都有对应的作用域
2.不同点:
2.1 在类中声明的位置的不同
属性:直接定义在类的一对{}内
局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量
2.2 关于权限修饰符的不同
属性:可以在声明属性时,指明其权限,使用权限修饰符。
常用的权限修饰符:private、public 、缺省、protected ---->封装性
局部变量:不可以使用权限修饰符。
2.3默认初始化值的情况:
属性:类的属性,根据其类型,都默认初始化值。
整型 (byte、short、int 、long: 0)
浮点型 (float、double: 0.0)
字符型 (char: 0 (或'\u0000'))
布尔型 (boolean: false)
引用数据类型(类、数组、接口:null) 局部变量:没默认初始化值。
意味着,我们在调用局部变量之前,一定要显示赋值。
特别地,形参在调用时,我们赋值即可。
2.4 在内存中加载的位置:
属性:加载到堆空间中 (非static)
局部变量:加载到栈空间
3.属性赋值的先后顺序:
A.默认初始化 B.显示初始化 C.构造器中赋值 D.通过“对象.方法” 或 “对象.
一、下载并安装git 1.下载地址: Git (git-scm.com)https://git-scm.com/这里使用官网下载地址。
2.安装 直接点击安装包,除了安装地址自己自定义之外,其他地方均可点击next。
当你点击鼠标右键可以看到这两个选项时,证明安装git成功。
二、设置账号名称和登录邮箱(建议使用qq邮箱) 鼠标右键点击Git Bash here会出现以下画面
如果觉得字太小在该界面鼠标右键Options
可根据个人习惯选择字体、大小。
分别输入以下指令以设置账号名称及邮箱:
git config --global user.name '账号名称'
git config --global user.email '邮箱'
可直接复制粘贴但在该界面不能Ctrl V只能通过鼠标右键粘贴
之后使用git生成密钥(在之后使用gitee中使用),在刚刚那个界面继续输入以下指令:
ssh-keygen -t rsa -C '邮箱'
该邮箱就是之前设置的邮箱
此处会让你输入三次,直接回车三次就行,无需填入任何信息。
根据图中所说的目录
可出现如下两个文件:
三、注册登录gitee,并设置密钥。 1.注册登录giteeGitee - 基于 Git 的代码托管和研发协作平台https://gitee.com/ 直接登录填写信息注册,使用刚刚自己在git设置的账户名称和邮箱注册。例:
2.设置公钥 注册登录完成之后进入主页,点击设置
右侧点击ssh公钥,并设置
标题可以自定义
公钥则是选择刚刚生成的公钥,点击名为”id_rsa.pub“的文件,以文本的格式将其打开,并复制其所有内容,粘贴到此处。点击确定,完成设置密钥。
3.检查SSH是否能够连接成功 鼠标右键点击Git Bash here,输入以下指令
ssh -T git@gitee.com
输入yes,之后再次输入上述指令,如出现”Hi“,表示连接成功。
四、设置IDEA 1.在IDEA中配置gitee 在IDEA中先随便创建一个项目,以便测试gitee。之后点击File-->Settings.
找到Version Control中的Git,点击右侧Test,下方就会出现Git version,显示Git版本。
之后找到Plugins,在Marketplace中搜索Gitee,点击安装。
安装之后,会提示Restart IDE,点击重启IDEA安装之后就会在Version Control中找到gitee。
点击Add account,添加码云(gitee)账户,之后点击Apply并退出
2.上传一个项目到码云测试。 点击工具栏,VCS中的Import into Version Control————>Share project on Gitee
日志目录
日志索引
日志存储
日志清理 Kafka将消息存储在磁盘中,为了控制磁盘占用间的不断增加就需要对消息做一定的清理操作。Kafka 中每个分区副本都对应一个Log ,而Log又可以分为多个日志分段,这样也便于日志的清理操作。 Kafka 提供了两种日志清理策略。
日志删除(Log Retention):按照一定的保留策略直接删除不符合条件的日志分段。日志压缩(Log Compaction):针对每个消息的key进行整合,对于有相同key 的不value值,只保留最后一个版本。 我们可以通过 broker端参数log.cleanup.policy来设置日志清理策略, 参数的默认值为“delete”,即采用日志删除的清理策略。如果要采用日志压缩的清理策略,就需要将log.cleanup.policy设置为“compact ”,并且还需要将 log.cleaner.enable(默认值为true )设定为 true。通过将log.cleanup.policy参数设置为 “delete,compact”,还可以同时支持日志删除和日志压缩两种策略。日志清理的粒度可以控制到主题级别,比如与log.cleanup.policy对应的主题级别的参数为cleanup.policy ,为了简化说明,本节只采用 broker 端参数做陈述。
日志删除 在kafka 的日志管理器中会有一个专门的日志删除任务来周期性地检测和删除不符合保留条件的日志分段文件,这个周期可以通过 broke 端参数log.retention.check.interval.ms来配置,默认值为 00000 ,即5分钟。当前日志分段的保留策略有3种: 基于时间的保留策略、基于日志大小的保留策略、基于日志起始偏移量的保留策略。
1、基于时间 日志删除任务会检查当前日志文件中是否有保留时间超过设定的阈值(retentionMs)来寻找可删除的日志分段文件集合( deletebleSegments ),如下图所示。 retentionMs可以通 broker端参数 log.retention.hours、log.retention.minutes和log.retention.ms来配其中log.retention.ms的优先级最高log.retention.minutes次之,log.retention.hours最低。默认情况下只配置了log.retention.hours 参数,其值为168故默认情况下日志分段文件的保留时间为7天。
查找过期的日志分段文件,并不是简单地根据日志分段的最近修改时间 lastModifiedTime来计算的,而是根据日志分段中最大的时间戳largestTimeStamp来计算 。因为日志分段lastModifiedTime可以被有意或无意地修改,比如执行了touch操作,或者分区副本进行了重新分配, lastModifiedTime并不能真实地反映出日志分段在磁盘的保留时间 要获取日志分段中的最大时间戳largestTimeStamp的值,首先要查询该日志分段所对应的时间戳索引文件,查找时间戳索引文件中最后一条索引项,若最后一条索引项的时间戳字段值大于0,则取其值,否则才设置为最近修改时间lastModifiedTime。
若删除的日志分段的总数等于该日志文件中所有的日志分段的数量,那么说明所有的日志分段都己过期,但该日志文件中还要有一个日志分段用于接收消息的写入,即必须要保证有一个活跃的日志分段activeSegment,在此种情况下,会先切分出一个新的日志分段作为activeSegment然后执行删除操作。
删除日志分段时, 首先会从log对象中所维护日志分段的跳跃表中移除待删除的日志分段,保证没有线程对这些日志分段进行读取操作。然后将日志分段所对应的所有文件添上".deleted"的后缀(当然也包括对应的索引文件) 最后交由一个以"delete-file"命名的延迟任务来删除这些以".deleted"为后缀的文件,这个任务的延迟执行时间可以通过file.delete.delay.ms参数来调配,此参数的默认值为60000,即1分钟。
2、基于日志大小 日志删除任务会检查当前日志的大小是否超过设定的阔值(retentionSize)来寻找可删除的日志分段的文件集合( deletableSegments ),如下图所示retentionSize可以通过broker端参数log.retention.bytes来配置,默认值为-1,表示无穷大。注意log.retention.bytes配置的是 Log 中所有日志文件的总大小,而不是单个日志分段(确切地说应该为.log日志文件)的大小。单个日志分段的大小由 broker端数log.retention.bytes来限制,默认值为1073741824,即 1GB。
基于日志大小的保留策略与基于时间的保留策略类似,首先计算日志文件的总大小 size和retentionSize差值diff,即计算需要删除的日志总大小,然后从日志文件中的第一个日志分段开始进行查找可删除的日志分段的文件集合 deletableSegments 。查找出deletableSegments之后就执行删除操作,这个删除操作和基于时间的保留策略的删除操作相同,这里不再赘述。
1、什么是KMP算法 K MP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息。KMP算法的时间复杂度O(m+n) [1] 。来自-------百度百科。
2、KMP算法有什么用 快速模式匹配算法,简称 KMP 算法,是在 BF 算法基础上改进得到的算法。
要是没有了解BF算法的话可以去看看我之前写的文章:(49条消息) 拳打脚踢解决BF算法QAQ_banbanbanni的博客-CSDN博客
BF算法就是暴力算法,挨个遍历主串来寻找子串,这种方法其实效率并不高,而且也比较浪费时间,
KMP的算法接近人为进行模式匹配的过程.就比如我们现在有一个主串"ABCABCE",我们需要在这个主串中寻找一个子串"ABCE"。
BF的方法我们不难发现我们匹配了四次才匹配到了子串的位置
我们不难发现为了寻找这个子串我们i连续遍历了4次,其间还不算j对于子串的遍历每次一主串遍历失败,我们子串的 j就得从零开始 ,i也得从 i - j + 1开始从头再来 ,显得很麻烦。效率很低
但是我们用KMP就可以简单很多,KMP的遍历就在于他的i 会一直往前走,不会后退,而且他的 j也不会因为一次失败匹配就倒退回到 j = 0的位置。
这样就便利了很多,那么问题来了,我们改如何判断j应该下一次应该跳到什么位置呢?
答案是next数组,但是next数组是什么呢?我们如何构建他呢?
接下来我们来探究探究他的奥秘所在。
三、什么是NEXT数组? 其实next数组就是一个前缀表,什么是前缀表呢?
前缀表就是用来回退的,它记录了模式串与主串(文本串)不匹配的时候,模式串应该从哪里开始重新匹配。
就用刚刚的嘞个KMP算法的例子来看当我们发现f != b的时候按理来说我们应该我们应该从头再来慢慢的匹配这个东西,但是他并没有,我们的前缀表就不会从头匹配,而是从上次已经匹配的内容开始匹配,找到了模式串中第三个字符b继续开始匹配。
那么前缀表是如何记录的呢?接下来我用一张图来解释这个前缀表的一个记录过程
我们不难发现,实际上就是记录下标i之前(包括i)的字符串中,有多大长度的相同前缀后缀。
因此这个字符串的前缀表为 0 1 0 0 2 0。
而我们的next数组实际上是把数组整体往右边移动一位,然后数组第一位为 -1,数组最后一个元素舍去,其实这并不涉及到KMP的原理,而是具体实现,next数组即可以就是前缀表,也可以是前缀表统一减一(右移一位,初始位置为-1)。
四、如何去实现next数组 构建一个next数组的过程其实也就是构建一个前缀表的过程
1.构建数组 首先我们得构建一个数组并且初始化数组
int* next =(int*)malloc(sizeof(int)*sublen);//因为和子串长度一样 2.初始化数组 next[0] = -1; next[1] = 0; int i = 2;//当前的i下标 int k = 0;//代表前一项的k k从第一位开始遍历前缀,i 往后开始遍历后缀,因此初始化 i = 2 ,k = 0;
日志目录
日志索引
日志存储
文件目录布局 Kafka 中的消息是以主题为基本单位进行归类的,各个主题在逻辑上相互独立。每个主题又可以分为一个或多个分区,分区的数量可以在主题创建的时候指定,也可以在之后修改。每条消息在发送的时候会根据分区规则被迫加到指定的分区中,分区中的每条消息都会被分配一个唯一的序列号,也就是通常所说的偏移量(offset )。
总的来说就是:
一个主题(topic)对应多个分区(partition)、一个分区对应多个副本(replica)、一个副本对应一个日志(log)、一个日志由多个日志分段(segment)组成。
log在物理上以文件夹的形式存在,segment对应磁盘上的一个日志文件和两个索引文件(.index、.timeindex),以及其它可能的文件(.delete、.cleaned、.swap、.snapshot、.txnindex、.leader-epoch-checkpoint)。
日志文件关系图
Log 中追加消息时是顺序写入的,只有最后一个 LogSegment 才能执行写入操作,在此之前所有的 LogSegment 都不能写入数据。我们将最后 LogSegment 称为"activeSegment",表示当前活跃的日志分段。随着消息的不断写入,当 activeSegment 满足定的条件时,就需要创建新的 activeSegment ,之后追加的消息将写入新的activeSegment。
每 LogSegment 都有一个基准偏移量(64位)baseOffset ,用来表示当前 LogSegment中第一条消息的 offset。日志文件和两个索引文件都是根据基准偏移量( baseOffset )命名的,名称固定为 20 位数字。
创建一个主题topic-demo,查看它分区0下的日志结构:
kafka存储log的根目录下还有5个默认的检查点文件
cleaner-offset-checkpoint log-start-offset-checkpoint meta.properties recovery-point-offset-checkpoint replication-offset-checkpoint
日志目录
日志索引
日志存储
日志索引 每个日志分段文件对应了两个索引文件,主要用来提高查找消息的效率。偏移量索引文件用来建立消息偏移量( offset )到物理地址之间的映射关系,方便快速定位消息所在的物理文件位置;时间戳索引文件则根据指定的时间戳( timestamp )来查找对应的偏移量信息。
索引文件以稀疏索引( sparse index )的方式构造消息的索引,它并不保证每个消息在索引文件中都有对应的索引项,每当写入一定量(log.index.interval.bytes 指定,默认值为 4096 ,即 4KB )的消息时,偏移量索引文件和时间戳索引文件分别增加一个偏移量索引项和时间戳索引项,增大或减小 log.index.interval.bytes 的值,对应地可以增加或缩小索引项的密度。
稀疏索引通过MappedByteBuffer将索引文件映射到内存中,以加快索引的查询速度。偏移量索引文件中的偏移量是单调递增的。查询指定偏移量时:1、使用二分查找法来快速定位偏移量的位置,2、如果指定的偏移量不在索引文件中,则会返回小于指定偏移量的最大偏移量。时间戳索引文件中的时间戳也保持严格的单调递增,查询指定时间戳时,也根据二分查找法来查找不大于该时间戳的最大偏移量,至于要找到对应的物理文件位置还需要根据偏移量索引文件来进行再次定位。稀疏索引的方式是在磁盘空间、内存空间、查找时间等多方面之间的一个折中。
日志分段文件达到一定的条件时需要进行切分,那么其对应的索引文件也需要进行切分。日志分段文件切分条件,满足以下其一即可:
当前日志分段文件的大小超过了 broker 端参数 log.segment.bytes的值。log.segment.bytes 参数的默认值为 1073741824 ,即 lGB。当前日志分段中消息的最大时间戳与当前系统的时间戳的差值大于 log.roll.ms或log.roll.hours参数配置的值。如果同时配置了 log.roll.ms或log.roll.hours参数,那么 log.roll.ms 的优先级高。默认情况下,只配置了log.roll.hours参数,其值为168=7天。偏移量索引文件或时间戳索引文件的大小达到 broker 端参数log.index.size.max.bytes配置的值。 默认值为 10485760 ,即 10MB。追加的消息的偏移量与当前日志分段的偏移量之间的差值大于 Integer.MAX_VALUE,即要追加的消息的偏移量不能转变为相对偏移量(offset-baseOffset > Integer.MAX_VALUE)。 偏移量索引 偏移量索引项的格式如图所示。每个索引项占用8个字节,分为两个部分。
relativeOffset:相对偏移量,表示消息相对于baseOffset的偏移量,占用4字节,当前索引文件的文件名即为baseOffset。position:物理地址,也就是消息在日志分段文件中对应的物理位置,占用4个字节。
消息的偏移量( offset )占用8个字节,也可以称为绝对偏移量。 偏移量索引示意图
如果我们要查找偏移量为233的消息,那么应该怎么做呢? 首先通过二分法在偏移量索引文件中找到不大于 23最大索引项,即【22,656】,然后从日志分段文件中的物理位置656开始顺序查找偏移量23的消息.
以上是最简单的一种情况。参考下图如果要查找偏移 268 的消息,那么应该怎么办呢?首先肯定是定位到 baseOffset为251的日志分段,然后计算相对偏移量 relativeOffset = 268 - 251=17 ,之后再在对应的索引文件中找到不大于17的索引项,最后根据索引项中的 position定位到具体的日志分段文件位置开始查找目标消息。那么又是如何查找 baseOffset 251的日志分段的呢?这里并不是顺序查找,而是用了跳跃表的结构 Kafka 的每个日志对象中使用了ConcurrentSkipListMap来保存各个日志分段,每个日志分段的 baseOffset 作为 key ,这样可以根据指定偏移量来快速定位到消息所在的日志分段。
你好,我是洋一,一个持续向上生长的互联网人。
再三考虑,准备出一些 Java面试系列 的文章,希望对你有帮助。
问你 线上生产服务器 CPU 100%了,你是如何排查、定位以及解决问题?
作甚 面试官问你,主要是想看看你有没有处理高负载的线上问题。考察对于此类问题,是否有一套自己的打法,是否你能熟练运用一些命令去排查、定位和解决问题的能力。对于开发来讲,是基本功,是需要主动掌握的。
解决 一般 CPU 100%,基本都是代码死循环造成的。
排查的核心思路是 找到对应服务器,定位是哪个进程的哪个线程中的哪些代码引发的问题,可以简单介绍当时的异常代码示例。
1. 使用 top -c 命令定位当前进程 top -c,可以显示当前进程的运行列表,然后输入 P,按照 CPU 的使用率进行排序。
如上图仅为演示效果,这样我们就能很清晰地看到哪个进程的 CPU 负载最大。比如 显示进程 PID 为 2479501 的 Java进程负载消耗最大。
2. 定位负载最大进程对应的线程 使用命令 top -Hp 2479501 找到这个进程对应的线程,然后输入 P ,按照 CPU 的使用率进行排序。
如上图所示,我们可以看到 2479508 耗费 CPU 最大。
3. 定位哪段代码导致 CPU 过高 因线程 PID 2479508 是十进制,我们需要将其转换为 十六进制 ,为什么要将十进制转换为十六进制 ?因为计算机需要二进制,十六是二的四次方,而十进制不是二的整数次幂,十六进制方便我们可读。比如,其转换结果是:25d594
接着,我们需要使用 jstack 打印进程的堆栈信息,再通过 grep 查看对应线程相关的东西。
jstack 2479501 | grep ‘25d594’ -C5 --color 这个时候就可以打印出代码,基本上帮助我们定位到出问题的位置,可以看到是哪个类中的哪个方法导致此次 CPU 100% 的原因了。
剑指offe题目的题解,为了方便回顾和记忆。答案来自leetcode下面的评论和题解进行整理,算法小白,只能先做抄题记录,
题解算是转载吧,但是转载要投原链接比较多就投的原创。仅作私人笔记用途。
剑指 Offer 09. 用两个栈实现队列 一个入栈,一个出栈。
如果入栈
class CQueue { public Stack<Integer> stack_in; public Stack<Integer> stack_out; public CQueue() { stack_in = new Stack<Integer>(); stack_out = new Stack<Integer>(); } public void appendTail(int value) { stack_in.push(value); } public int deleteHead() { if(!stack_out.isEmpty()){ return stack_out.pop(); }else{ while(!stack_in.isEmpty()){ stack_out.push(stack_in.pop()); } return stack_out.isEmpty()?-1:stack_out.pop(); } } } 剑指 Offer 30. 包含min函数的栈 用两个栈A和B,A中正常存放,B只放当前遇到的最小的值。
pop的时候如果A的顶层元素和B的顶层元素相等的时候B也需要pop
class MinStack { Stack<Integer> A,B; /** initialize your data structure here. */ public MinStack() { A=new Stack<Integer>(); B=new Stack<Integer>(); } public void push(int x) { A.
简介 Rust是一门赋予每个人构建可靠且高效软件能力的编程语言。可靠主要体现在安全性上。其高效不仅限于开发效率,它的执行效率也是令人称赞的,是一种少有的兼顾开发效率和执行效率的语言。Rust 语言由 Mozilla 开发,最早发布于 2014 年 9 月。Rust 的编译器是在 MIT License 和 Apache License 2.0 双重协议声明下的免费开源软件。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
特性 高性能:Rust 速度惊人且内存利用率极高。由于没有运行时和垃圾回收,它能够胜任对性能要求特别高的服务,可以在嵌入式设备上运行,还能轻松和其他语言集成。
可靠性:Rust 丰富的类型系统和所有权模型保证了内存安全和线程安全,让您在编译期就能够消除各种各样的错误。
生产力:Rust 拥有出色的文档、友好的编译器和清晰的错误提示信息, 还集成了一流的工具——包管理器和构建工具, 智能地自动补全和类型检验的多编辑器支持, 以及自动格式化代码等等。
Rustacean:使用 rust 的攻城狮不叫 ruster 而是叫 Rustacean ,咱也不知道为什么,书上就是这么说的。
特征 作为一门编程语言,rust既可以分类为面向过程编程语言,也可以分类为面向对象编程语言rust拥有精细化的基础数据结构rust中支持泛型,并且拥有泛型枚举rust中支持接口,甚至支持接口默认方法,并且接口既可以作为方法入参也可以作为方法出参 用途 传统命令行程序嵌入式网络服务WebAssemblyWeb服务… 安装 以 windows 11 为例
下载 rustup-init.exe ,双击此可执行程序会打开一个命令行程序,此程序引导安装,具体安装过程:
Rust Visual C++ prerequisites Rust requires the Microsoft C++ build tools for Visual Studio 2013 or later, but they don't seem to be installed.
第一步,点击Report>Report Temlates 制作模板
第二步,时间问题,我们在PATH小图标中 ,选择我们已经做好的一个FDATemplate 模板,并双击,没有模版的朋友,点New图标
这时候,我们左右2个区,Aavailable区域中选择你想要在文档中展示的东东,这里我们选择List of Tables,和List of Table Columns[数据表格信息]
如图,右键点击,Selection
选择你想要在数据表格中展示的信息,想要展示的就打钩
鼠标右键选择LAYOUT样式功能
制作样式
点击保存,一个简单的RTP文档就制作完成了。
我们导出WORD文档
在点击OK按钮之后,就会产生我们期待已久的,WORD文档了
I List of tables Name
Code
FDACaseAccept
FDACaseAccept
FDACaseAcceptDeal
FDACaseAcceptDeal
FDACaseAcceptRevert
FDACaseAcceptRevert
FDACaseCategory
FDACaseCategory
FDACaseDocumentMonitor
FDACaseDocumentMonitor
FDACaseReason
FDACaseReason
FDACaseSources
FDACaseSources
FDACaseSourcesWay
FDACaseSourcesWay
FDACaseSuspectMoney
FDACaseSuspectMoney
II FDACaseAccept Code
Comment
Data Type
Mandatory
Default
Primary
Foreign Key
AcceptCodeID
案件编码
varchar(15)
FALSE
FALSE
FALSE
AcceptId
ID主键
numeric
TRUE
TRUE
FALSE
AcceptUserID
受理人ID
int
A. 三升序列(5 分)
答案:
VLPWJVVNNZSWFGHSFRBCOIJTPYNEURPIGKQGPSXUGNELGRVZAG SDLLOVGRTWEYZKKXNKIRWGZWXWRHKXFASATDWZAPZRNHTNNGQF ZGUGXVQDQAEAHOQEADMWWXFBXECKAVIGPTKTTQFWSWPKRPSMGA BDGMGYHAOPPRRHKYZCMFZEDELCALTBSWNTAODXYVHQNDASUFRL YVYWQZUTEPFSFXLTZBMBQETXGXFUEBHGMJKBPNIHMYOELYZIKH ZYZHSLTCGNANNXTUJGBYKUOJMGOGRDPKEUGVHNZJZHDUNRERBU XFPTZKTPVQPJEMBHNTUBSMIYEGXNWQSBZMHMDRZZMJPZQTCWLR ZNXOKBITTPSHEXWHZXFLWEMPZTBVNKNYSHCIQRIKQHFRAYWOPG MHJKFYYBQSDPOVJICWWGGCOZSBGLSOXOFDAADZYEOBKDDTMQPA VIDPIGELBYMEVQLASLQRUKMXSEWGHRSFVXOMHSJWWXHIBCGVIF GWRFRFLHAMYWYZOIQODBIHHRIIMWJWJGYPFAHZZWJKRGOISUJC EKQKKPNEYCBWOQHTYFHHQZRLFNDOVXTWASSQWXKBIVTKTUIASK PEKNJFIVBKOZUEPPHIWLUBFUDWPIDRJKAZVJKPBRHCRMGNMFWW CGZAXHXPDELTACGUWBXWNNZNDQYYCIQRJCULIEBQBLLMJEUSZP RWHHQMBIJWTQPUFNAESPZHAQARNIDUCRYQAZMNVRVZUJOZUDGS PFGAYBDEECHUXFUZIKAXYDFWJNSAOPJYWUIEJSCORRBVQHCHMR JNVIPVEMQSHCCAXMWEFSYIGFPIXNIDXOTXTNBCHSHUZGKXFECL YZBAIIOTWLREPZISBGJLQDALKZUKEQMKLDIPXJEPENEIPWFDLP HBQKWJFLSEXVILKYPNSWUZLDCRTAYUUPEITQJEITZRQMMAQNLN DQDJGOWMBFKAIGWEAJOISPFPLULIWVVALLIIHBGEZLGRHRCKGF LXYPCVPNUKSWCCGXEYTEBAWRLWDWNHHNNNWQNIIBUCGUJYMRYW CZDKISKUSBPFHVGSAVJBDMNPSDKFRXVVPLVAQUGVUJEXSZFGFQ IYIJGISUANRAXTGQLAVFMQTICKQAHLEBGHAVOVVPEXIMLFWIYI ZIIFSOPCMAWCBPKWZBUQPQLGSNIBFADUUJJHPAIUVVNWNWKDZB HGTEEIISFGIUEUOWXVTPJDVACYQYFQUCXOXOSSMXLZDQESHXKP FEBZHJAGIFGXSMRDKGONGELOALLSYDVILRWAPXXBPOOSWZNEAS VJGMAOFLGYIFLJTEKDNIWHJAABCASFMAKIENSYIZZSLRSUIPCJ BMQGMPDRCPGWKTPLOTAINXZAAJWCPUJHPOUYWNWHZAKCDMZDSR RRARTVHZYYCEDXJQNQAINQVDJCZCZLCQWQQIKUYMYMOVMNCBVY ABTCRRUXVGYLZILFLOFYVWFFBZNFWDZOADRDCLIRFKBFBHMAXX 思路:
B.最优旅行 (5分)
答案:
车次 出发站 到达站 出发时间 到达时间 G169 北京 上海 16:40 22:35 G21 北京 上海 19:08 23:40 G18 上海 北京 17:55 22:36 G68 广州 北京 11:13 21:10 G67 北京 广州 12:13 22:19 G1305 上海 广州 15:25 23:38 G86 广州 上海 08:00 14:50 G6122 广州 长沙 21:00 23:36 G6117 长沙 广州 17:55 20:39 G502 长沙 北京 07:36 14:24 G503 北京 长沙 14:41 21:14 G1359 上海 长沙 15:37 20:59 G1348 长沙 上海 09:00 13:41 G362 西安 上海 08:49 14:45 G1936 上海 西安 16:12 22:54 G87 北京 西安 14:00 18:20 G88 西安 北京 13:30 17:55 G98 西安 广州 09:57 17:39 G836 广州 西安 11:24 20:09 G1404 广州 杭州 15:56 23:25 G20 杭州 北京 07:48 12:20 G39 北京 杭州 19:04 23:22 G7355 上海 杭州 21:30 22:28 G7558 杭州 上海 07:06 08:12 G300 济南 上海 06:50 11:40 G333 北京 济南 19:55 21:55 G336 济南 北京 07:45 09:33 G2056 广州 济南 08:05 18:34 G2058 济南 广州 10:14 20:49 G350 成都 北京 07:00 14:46 G89 北京 成都 06:53 14:38 G1888 成都 南京 11:28 22:00 G7180 上海 南京 10:05 11:29 G7003 南京 上海 08:00 09:39 G7613 南京 杭州 16:19 17:40 G7604 杭州 南京 12:09 13:30 G1540 昆明 南京 10:20 21:14 G1539 南京 昆明 09:05 19:40 G2883 成都 昆明 08:51 14:29 G2884 昆明 成都 12:16 17:57 G1538 昆明 郑州 08:46 18:48 G1537 郑州 昆明 10:38 20:49 G2001 郑州 西安 07:52 10:24 G2002 西安 郑州 08:10 10:29 G2231 西安 重庆 17:06 22:56 G2232 重庆 西安 07:05 12:37 G8594 重庆 成都 06:50 08:07 G8599 成都 重庆 22:12 23:29 G1709 天津 重庆 08:05 19:39 G1710 重庆 天津 10:49 22:45 G8901 北京 天津 22:10 22:45 G8928 天津 北京 19:08 19:46 G2609 天津 太原 10:40 14:15 G2610 太原 天津 14:43 18:12 G1954 太原 上海 12:26 21:17 G1952 上海 太原 08:10 17:28 G686 郑州 太原 13:17 17:16 G688 太原 郑州 17:38 21:38 G1864 太原 杭州 12:50 21:10 G1862 杭州 太原 07:14 15:50 G91 北京 太原 08:40 11:07 G92 太原 北京 08:33 11:00 G694 太原 武汉 16:37 22:29 G692 武汉 太原 09:48 16:00 G1722 武汉 上海 08:00 11:53 G1720 上海 武汉 13:51 17:50 G858 西安 武汉 15:18 19:48 G856 武汉 西安 09:17 14:27 G365 天津 武汉 14:56 20:41 G366 武汉 天津 14:30 20:32 G294 长沙 天津 08:47 16:56 G292 天津 长沙 10:58 18:50 G696 长沙 太原 09:23 17:55 G698 太原 长沙 10:46 18:18 G1391 杭州 昆明 11:43 22:53 G1392 昆明 杭州 09:06 20:18 G1514 昆明 南昌 16:00 22:54 G1511 南昌 昆明 08:25 15:38 G1462 南昌 杭州 12:24 15:28 G1451 杭州 南昌 12:30 15:26 G1244 济南 长春 07:42 15:07 G1242 长春 济南 15:33 22:35 G8033 沈阳 长春 06:42 08:40 G1290 长沙 长春 07:21 21:09 G1292 长春 长沙 08:47 22:08 G400 长春 北京 08:32 14:48 G399 北京 长春 15:20 21:45 G1886 南京 成都 08:07 17:54 G579 南京 长沙 09:27 14:10 G580 长沙 南京 15:53 20:40 G1484 贵阳 南京 07:58 18:02 G2335 南京 贵阳 12:07 21:58 G2105 长沙 贵阳 13:17 16:55 G2116 贵阳 长沙 08:11 11:26 G2201 郑州 成都 07:10 13:19 G2212 成都 郑州 16:57 23:04 G1814 上海 郑州 14:15 18:12 G370 郑州 上海 07:33 12:02 G1274 武汉 沈阳 07:23 19:03 G1272 沈阳 武汉 07:32 19:20 G2869 重庆 昆明 07:43 11:55 G2870 昆明 重庆 14:52 19:09 G1335 重庆 上海 08:48 20:56 G1333 上海 重庆 11:39 23:29 G1759 南昌 重庆 07:08 14:45 G1761 重庆 南昌 15:12 22:23 G1493 南京 南昌 13:00 17:21 G1496 南昌 南京 09:04 13:25 G5314 南昌 福州 08:13 11:09 G5312 福州 南昌 18:30 21:25 G1256 长春 上海 11:53 22:54 G1258 上海 长春 09:08 20:05 G1284 沈阳 成都 07:02 21:47 G1282 成都 沈阳 09:06 23:13 G217 北京 沈阳 13:30 17:15 G218 沈阳 北京 08:11 11:58 G2604 沈阳 太原 15:34 23:00 G2602 太原 沈阳 07:44 15:14 G8664 贵阳 成都 19:15 22:35 G8691 成都 贵阳 11:11 14:31 G2958 贵阳 广州 14:03 20:26 G2960 广州 贵阳 07:27 13:43 G1521 武汉 贵阳 08:01 13:25 G1524 贵阳 武汉 14:23 19:33 G1609 福州 广州 08:16 14:15 G1607 广州 福州 14:55 21:05 G1696 昆明 福州 11:11 22:02 G1698 福州 昆明 08:41 19:28 G1636 福州 上海 12:26 16:55 G1631 上海 福州 07:54 12:15 G1642 福州 杭州 14:45 18:32 G1641 杭州 福州 18:55 22:38 思路:
将字符串中某个子串反转,并返回新的字符串-尹白|尹白博客|Linux运维|Java开发|docker容器化技术实战
这道题,是对我们了解字符串的训练
public class StringTest4 { //题目4: 将字符串中某个子串反转,并返回新的字符串 public static void main(String[] args) { String str = "inbai.net"; String s = reverseString(str,0,str.length() -1); System.out.println(s); //结果: ten.iabni } /*** * 反转 * @param string 需要反转的字符串 * @param start 开始位置 * @param end 结束位置 * @return * */ public static String reverseString(String string, int start, int end) { char[] c = string.toCharArray(); return reverseArray(c, start, end); } /** * * @param c * @param start * @param end * @return * 原理分析: * 把第一个字符和最后一个字符交换位置, 然后,第一个位置向后走1, 最后一个位置向前走1 * * */ public static String reverseArray(char[] c, int start, int end) { for (int i = start, j = end; i < j; i++, j--) { char temp = c[i]; c[i] = c[j]; // c[j] = temp; } return new String(c); } }
原文地址:将字符串中某个子串反转,并返回新的字符串-尹白|尹白博客|Linux运维|Java开发|docker容器化技术实战
public class StringTest4 { //题目4: 将字符串中某个子串反转,并返回新的字符串 public static void main(String[] args) { String str = "inbai.net"; String s = reverseString(str,0,str.length() -1); System.out.println(s); //结果: ten.iabni } /*** * 反转 * @param string 需要反转的字符串 * @param start 开始位置 * @param end 结束位置 * @return * */ public static String reverseString(String string, int start, int end) { char[] c = string.toCharArray(); return reverseArray(c, start, end); } /** * * @param c * @param start * @param end * @return * 原理分析: * 把第一个字符和最后一个字符交换位置, 然后,第一个位置向后走1, 最后一个位置向前走1 * * */ public static String reverseArray(char[] c, int start, int end) { for (int i = start, j = end; i < j; i++, j--) { char temp = c[i]; c[i] = c[j]; // c[j] = temp; } return new String(c); } } 这道javaString面试题,主要有两个知识点,一个就是考我们对于String类转char数组的知识点, 还一个就是考我们对for循环的使用,当然了, 也有一点点的算法在里面,从而实现将字符串中某个子串反转,并返回新的字符串的操作.
matplotlib.pyplot使用for循环进行多个子图Subplot的绘制 目录 matplotlib.pyplot使用for循环进行多个子图Subplot的绘制一、matplotlib.pyplot绘制子图的基本方法二、使用for循环进行绘图的一种方法 一、matplotlib.pyplot绘制子图的基本方法 首先我们来了解一下,matplotlib中绘图需要使用到的元素
首先是figure图片对象,然后是图片对象包含的子图对象axes,再然后是每个子图对象的轴Axis对象。
我们要进行子图的绘制,首先我们要创建图片对象,然后再创建子图对象,在子图对象上进行绘制,可以使用多种方法。
第一种:
plt.figure() plt.plot([1, 2, 3]) 我们使用plt.figure()创建了一个图片对象,但是没有给这个图片对象指定引用,这里plt.plot()会自动在已经当前正在使用的figure上进行绘制。效果就如上图所示。
第二种:
创建子图对象然后进行绘制。
fig = plt.figure() ax1 = plt.subplot(121) ax2 = plt.subplot(122) ax1.plot([1,2,3]) ax2.scatter(1,1) 第三种:
同时创建figure和子图对象
fig, axes = plt.subplots(2, 2) axes[0, 1].plot([1, 2, 3]) axes[1, 1].plot([1, 2, 3]) 这里的axes是一个numpy的高维数组ndarray
我们不能直接对axes进行操作进行绘图,我们只能访问其中一个元素获得一个ax后然后再进行绘图。
二、使用for循环进行绘图的一种方法 当我们的绘图语句非常多的时候,代码会显得繁琐,我们需要一种方式来进行循环绘图,但是axes是个ndarray这就限制了我们使用for循环直接来迭代这个高维数组,这样的思路是行不通的,那我们换一个思路。既然axes的类型是ndarry,那么axes肯定有shape属性,可以访问axes的行和列数,这正好和我们指定子图的位置一致。
我们使用一个list,来保存axes中的每一个子图对象,这样我们接下来使用时就方便迭代了
fig, axes = plt.subplots(3, 3) axes_list = [] for i in range(axes.shape[0]): for j in range(axes.shape[1]): axes_list.append(axes[i, j]) print(axes_list) fig, axes = plt.subplots(3, 3) axes_list = [] for i in range(axes.
目录
一 SREWorks 是什么?
二 SREWorks 有什么优势?
体系化运维平台分层架构
完整的数据化运维体系实践
服务化的 AIOps 智能运维平台
运维中台化、低代码化及云原生化运维开发体验
三 为什么要开源?
四 后续规划
五 写在最后
作者:晟白
随着行业不断发展,大数据&AI也逐渐呈现云原生化的趋势。复杂的业务场景及其背后涉及到的不同技术方向的开源和自研,使得产品运维面临技术复杂度高、规模大、场景多等挑战。
阿里巴巴云原生大数据运维平台 SREWorks,沉淀了团队近10年经过内部业务锤炼的 SRE 工程实践,今天正式对外开源,秉承“数据化、智能化”运维思想,帮助运维行业更多的从业者采用“数智”思想做好高效运维。
一 SREWorks 是什么? 谷歌在2003年提出了一种岗位叫做 SRE (Site Reliability Engineer,站点可靠性工程师),它是软件工程师和系统管理员的结合,重视运维人员的开发能力,要求运维日常琐事在50%以内,另外50%精力开发自动化工具减少人力需求。
SREWorks 作为阿里云大数据SRE团队对SRE理念的工程实践,专注于以应用为中心的一站式“云原生”、“数智化”运维 SaaS 管理套件,提供企业应用&资源管理及运维开发两大核心能力,帮助企业实现云原生应用&资源的交付运维。
阿里云大数据 SRE 团队天然靠近大数据和AI,对大数据&AI技术非常熟悉,且具有随取随用的大数据&AI算力资源,一直努力践行“数据化”、“智能化”的运维理念,行业里的 DataOps(数据化运维)最早由该团队提出。SREWorks 中有一套端到端的 DataOps 闭环工程化实践,包括标准的运维数仓、数据运维平台、运营中心等。
随着云原生时代大趋势的到来,阿里云大数据 SRE 团队将SREWorks运维平台开源,希望为运维工程师们提供开箱即用的运维平台。
二 SREWorks 有什么优势? 回归到运维领域的需求,无论上层产品和业务形态怎么变化,运维本质上解决的还是“质量、成本、效率、安全”相关需求。SREWorks 用一个运维 SaaS 应用界面来支撑上述需求,同时以“数智”思想为内核驱动 SaaS 能力,具体包括交付、监测、管理、控制、运营、服务六部分。
体系化运维平台分层架构 从“质量、成本、效率、安全”四个维度出发看运维本质相关工作,运维除了要搭平台、建规范、做标准,还要用自动理念提升效率,用数据驱动测试/开发/运维,用智能手段提前发现/预测风险问题等。这些可以看成是方法论。如何能从理论快速获得一套体系化、工程化、产品化的能力实践,去支撑满足上述四个维度的需求,就是 SREWorks 所考虑的问题。
阿里云大数据 SRE 团队利用分层思想构筑了 SREWorks 平台产品体系,借鉴经典 SPI(SaaS/PaaS/IaaS)三层划分思路,SREWorks 由“运维 SaaS 应用场景层、运维 PaaS 中台服务层、运维 IaaS 接入层”三部分构成。
从Java实现回溯算法入门(排列+组合+子集)练习了使用回溯算法的基础使用。
使用回溯算法实现搜索才是回溯算法+DFS的使用。
文章目录 1.搜索问题79.单词搜索212.单词搜索Ⅱ130.被围绕的区域200.岛屿的数量22.括号生成113. 路径总和Ⅱ剑指 Offer 13. 机器人的运动范围 1.搜索问题 79.单词搜索 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
示例一:
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED" 输出:true 示例二:
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCB" 输出:false 示例三:
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "SEE" 输出:true 思路:
回溯算法+状态重置
使用布尔变量marked判断是否找到字符
代码实现:
class Solution { int rows, cols; // 定义行和列 char[][] board; char[] word; boolean[][] marked; // 用来存储是否搜索到字母 int[][] next = new int[][]{{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; //用来搜索上下左右,顺序不重要 public boolean exist(char[][] board, String word) { this.
一、一则出人意料的报告 前段时间,在开源中国看到一篇分享了目前最热门的技术技能的文章,该文章根据招聘机构Dice发布的Q3技术工作报告,指出了当下最热门技术能力,分别是SQL、Java、Python 和 Linux。如下图:
文章全篇都在谈论并分析各项热门技术能力的需求变化,并指出一些增长快速的技能的未来趋势。
可当我看到报告的截图时发现,需求更高、排名第一的项目管理能力,在文中并没有详细的提及,而是用了一句“雇主正在寻找了解软件开发和项目管理核心概念的技术人员,此外还需要具备 SQL、Java、Python 和 Linux 等技术技能”简单带过。
从截图中,我们可以清楚看到,项目管理能力在众多技术能力中排名第一,且是在SQL、Java、Python、Linux需求有所增长的情况下,仍旧稳居第一,这说明市场对项目管理能力的需求是非常大的。
可为何明明项目管理能力的需求如此之大,大家却鲜少关注?
最主要的一点,是大部分人认为项目管理能力“与我无关”,我无需具备进而忽略了这项能力。但程序员真的不需要这项能力吗?
互联网流传的“程序员35岁就会失业的‘魔咒’”,仿佛已经将他们的未来和年龄深度捆绑在一起,宣告着程序员的结局。人人惶恐、担忧自己的未来。
在职场中我们也或多或少看过甚至经历过这样的事:有些员工年纪轻轻,就已经是主管;而有些资深老员工,却仍在做一些基础的工作。
这些现状的背后,和项目管理能力不无关系。无论从职业发展还是个人成长来看,项目管理能力都不应该被人忽视。
二、项目管理能力的重要性 1. 项目管理能力是职场人必备技能 美国《财富》杂志曾指出,项目管理能力,已经成为一项职场人士的必备技能。可实际上,绝大多数程序员并没有意识到项目管理对自己的重要性。有时,忽略比不做,更让人损失。
项目管理能力并不只有管理层或项目经理才需要具备的。从职业发展来看,项目管理能力对自己的职业规划和进阶都有非常大的帮助,各种高级技术岗对工作的大局的掌控,也都会运用到项目管理能力。
作为职场“打工人”,我们应该拓宽自己的职业边界,为自己“增值”!《程序员生存手册》或许可以为你提供一些思路和干货,帮助你在不断发展和变化的世界中持续生存,更加优秀。
2. 人人都是自己的项目经理 我们人人都可以是自己的项目经理。这并不意味着人人都要有项目经理的权力,而是指要具备项目经理的思维和方法。生活中亦然。
项目不分大小,任何一件事情都可以看作一个项目,执行这件事情的人就都是项目经理。它可以是设计开发某一个产品功能,可以是一个学习计划,也可以是房屋装修改造、活动筹备、旅行等等。如果大家想学习了解有关项目管理的知识内容,欢迎到禅道学堂,我们为大家提供了大量知识内容,帮助大家学习并了解项目管理的知识。
做自己工作和生活中的项目经理!当我们用项目管理的思维来面对一件待解决的复杂事务时,它能明显让我们理清思路、考虑周全、明确行动并最终收获宝贵的经验。
目录
项目实现目标设计:
项目环境:
使用到的库:
Jsoncpp 库: 使用方法:
Bundle 库:
使用方法:
Httplib 库:
使用方法: C++17 filesystem库:
模块的实现: 服务端数据管理模块:
服务端热点管理模块:
服务端网络通信模块 与 业务处理模块:
客户端数据管理模块:
客户端目录检查模块:
客户端网络通信模块:
项目的不足及改进思路:
项目源码:
项目实现目标设计: 服务端程序: 部署在linux服务器上
实现针对客户端请求的业务处理: 文件的上传备份,以及客户端浏览器的查看以及下载功能, 并且具有热点管理功能和下载时断点续传功能,将非热点文件压缩存储节省磁盘空间
服务端模块划分设计:
网络通信模块: 实现与客户端进行网络通信,并进行http协议数据解析客户端请求
业务处理模块: 明确客户端请求,并且进行对应的业务处理(上传文件,备份信息获取,文件下载)数据管理模块: 对备份文件信息进行统一数据管理
热点管理模块: 对服务器上备份的文件进行热点管理,将非热点文件进行压缩存储
客户端程序: 部署在windows客户机上
实现针对客户端主机上指定文件夹中的文件,自动进行检测判断是否需要备份,需要则上传到服务器备份
客户端模块划分设计:
目录检测模块: 遍历客户端主机上的指定文件夹,获取文件夹下所有的文件信息
数据管理模块:管理客户端所备份的所有文件信息(判断一个文件是否需要备份:1.历史备份信息中不存在,2.历史备份信息存在但是不一致)
网络通信模块: 搭建网络通信客户端,将需需要备份的文件上传备份到服务器
项目环境: 服务器: centos7(以上)/ vim、g++(7.3以上)、gdb、makefile
客户端: Windows10/ vs2017(以上)
使用到的库: Jsoncpp 库: json 是一种数据交换格式,采用完全独立于编程语言的文本格式来存储和表示数据。比如将一个一个的键值对组织成这种格式:
jsoncpp 库用于实现 json 格式的序列化和反序列化,完成将多个数据对象组织成为 json 格式字符串,以及将 json 格式字符串解析得到多个数据对象的功能。
Simulator [ˈsɪmjəˌletɚ] 模拟器
KepServerEx是一款在工业控制中比较常见的数据采集服务软件之一,提供了多种类型的驱动,具有比较广泛的适用性。很多厂商和个人都会选择用它来做OPCServer。在项目的实施或测试过程中,我们有时会遇到身边没有传感器、PLC之类设备的情况,就无法通过实时数据来测试工作成果的有效性。幸运的是KepServerEx提供了数据模拟功能,可以提供多种类型、格式的模拟数据。下面就是具体的配置过程,重点在于模拟数据的函数( 斜坡函数、随机函数、正弦函数、User 函数)
=====================================================
欢迎大家加入交流讨论QQ群: 905485143 =====================================================
1. 配置过程: 创建Channel Channel即通道,可以将它理解为OPC中的Server。 设备驱动选择“Simulator”,即模拟器驱动。然后一直点击下一步完成... 通道名字随便取。 剩余几项设置也可以调整,如果需要可以自行调整 创建Device Device即设备,可以理解为OPC中的Group。
Device 随便起个名。 设备类型可以根据需要选择16位或8位。
设备ID,可以自行修改。
选择‘扫描模式’
下一步,完成。
创建Tag Tag即标签,可理解为OPC中的Item。现在才来到整篇文章的重点。 添加标签的界面包含两部分:
一部分是对标签的定义(Identification),包括名称(Name)、地址(Address)、描述(Description)
另一部分是数据的属性(Data Properties),包括数据类型(DataType )、读写类型(Client)、扫描频率(Scan Rate) 对我们而言,用处最大的就是Address,我们可以编写不同的函数放在Address中用来模拟不同类型的数据。官方文档提供了多种模拟函数供我们使用(可在帮助文档中找到)。
=====================================================
2. 模拟寄存器(可读/写) (B寄存器、K寄存器、R寄存器、S寄存器) B寄存器为布尔型, R 和 K 寄存器为数字数据, S 寄存器是可变长度字符串数据位置。
当 R 寄存器作为字符、字节、字、短整型、BCD、长整型、双字型、双长整型、四字型或 LBCD 引用时,它将通过每次读取时递增 1 的方式来模拟不断更改的数据。这些类型的数组在每次读取时递增 1。当 R 寄存器作为浮点型或双精度型引用时,值在每次读取时递增 1.25。浮点型或双精度型的数组在每次读取时递增 1.25。每种类型均有增量范围。对于浮点型,范围为 0 至 32767。对于双精度型,范围为 0 至 65535。
8 位设备地址 16 位设备地址 注意:
除位级布尔值之外,所有数据类型均支持数组 (将 [r] 或 [r][c] 附加到地址后面)。为数据类型指定的地址必须满足数据类型的完整大小。这意味着用户的写操作不能超出数据范围。 在标签创建界面可以设置标签的属性
目录
方法一 Random ran=new Random();
方法2 Math.random()
练习
生成随机数
生成随机字符串
在Java中我们想生成1~100的随机数该怎么操作呢,我们看下代码
方法一 Random ran=new Random(); public class TestDemo { public static void main(String[] args) { Random ran=new Random(); int ranNum=ran.nextInt(100);//[0,100) System.out.println(ranNum); } } 注意此时生成的随机数是小于100的如何解决呢
int ranNum=ran.nextInt(100)+1;//此时随机数为1~100 如何使生成的随机数唯一呢
Random ran=new Random(1234);//在Random中输入值此时生成随机值就固定了 方法2 Math.random() public static void main(String[] args) { int num=(int)(Math.random()); System.out.println(num); 看到结果好像生成的有问题这是为什么呢?
其实写法是没什么问题的但是生成的打印出来就是0,是因为Math.random生成随机数范围为[0,0.999999) 返回类型为double类型,知道了原因我们就可以很好的使用了
int num=(int)(Math.random()*100+1); 此时生成的随机数取值范围为1~100
练习 掌握了随机数的生成我们试着练习一下
生成随机数 public static void main(String[] args) { Scanner sca=new Scanner(System.in); Random ran=new Random(); int ranNum=ran.
JDK 、 JRE 、 JVM 之间的区别
JDK ( Java SE Development Kit ), Java 标准开发包,它提供了编译、运行 Java 程序所需的各种工具和资源,包括 Java 编译器、 Java 运行时环境,以及常用的 Java 类库等。
JRE ( Java Runt ime Environment ), Java 运行环境,用于运行 Java 的字节码文件。 JRE 中包括了 JVM 以及 JVM 工作所需要的类库,普通用户而只需要安装 JRE 来运行 Java 程序,而程序开发者必须安装 JDK 来编译、调试程序。
JVM ( Java Virtual Mechinal ), Java 虚拟机,是 JRE 的一部分,它是整个 java 实现跨平台的最核心的部分,负责运行字节码文件。
我们写 Java 代码,用 txt 就可以写,但是写出来的 Java 代码,想要运行,需要先编译成字节码,那就需要编译器,而 JDK 中就包含了编译器 javac ,编译之后的字节码,想要运行,就需要一个可以执行字节码的程序,这个程序就是 JVM ( Java 虚拟机),专门用来执行 Java 字节码的。
type为0 表示工作日
type为1 表示周末
type为2 表示节假日
{"dayStr":"20200101","type":"2"}, {"dayStr":"20200102","type":"0"}, {"dayStr":"20200103","type":"0"}, {"dayStr":"20200104","type":"1"}, {"dayStr":"20200105","type":"1"}, {"dayStr":"20200106","type":"0"}, {"dayStr":"20200107","type":"0"}, {"dayStr":"20200108","type":"0"}, {"dayStr":"20200109","type":"0"}, {"dayStr":"20200110","type":"0"}, {"dayStr":"20200111","type":"1"}, {"dayStr":"20200112","type":"1"}, {"dayStr":"20200113","type":"0"}, {"dayStr":"20200114","type":"0"}, {"dayStr":"20200115","type":"0"}, {"dayStr":"20200116","type":"0"}, {"dayStr":"20200117","type":"0"}, {"dayStr":"20200118","type":"1"}, {"dayStr":"20200119","type":"0"}, {"dayStr":"20200120","type":"0"}, {"dayStr":"20200121","type":"0"}, {"dayStr":"20200122","type":"0"}, {"dayStr":"20200123","type":"0"}, {"dayStr":"20200124","type":"2"}, {"dayStr":"20200125","type":"2"}, {"dayStr":"20200126","type":"2"}, {"dayStr":"20200127","type":"2"}, {"dayStr":"20200128","type":"2"}, {"dayStr":"20200129","type":"2"}, {"dayStr":"20200130","type":"2"}, {"dayStr":"20200131","type":"0"}, {"dayStr":"20200201","type":"0"}, {"dayStr":"20200202","type":"1"}, {"dayStr":"20200203","type":"0"}, {"dayStr":"20200204","type":"0"}, {"dayStr":"20200205","type":"0"}, {"dayStr":"20200206","type":"0"}, {"dayStr":"20200207","type":"0"}, {"dayStr":"20200208","type":"1"}, {"dayStr":"20200209","type":"1"}, {"dayStr":"20200210","type":"0"}, {"dayStr":"20200211","type":"0"}, {"dayStr":"20200212","type":"0"}, {"dayStr":"20200213","type":"0"}, {"dayStr":"20200214","type":"0"}, {"dayStr":"20200215","type":"1"}, {"dayStr":"20200216","type":"1"}, {"dayStr":"20200217","type":"0"}, {"dayStr":"20200218","type":"0"}, {"dayStr":"20200219","type":"0"}, {"dayStr":"20200220","type":"0"}, {"dayStr":"20200221","type":"0"}, {"dayStr":"20200222","type":"1"}, {"dayStr":"20200223","type":"1"}, {"dayStr":"20200224","type":"0"}, {"dayStr":"20200225","type":"0"}, {"dayStr":"20200226","type":"0"}, {"dayStr":"20200227","type":"0"}, {"dayStr":"20200228","type":"0"}, {"dayStr":"20200229","type":"1"}, {"dayStr":"20200301","type":"1"}, {"dayStr":"20200302","type":"0"}, {"dayStr":"20200303","type":"0"}, {"