前面的章节讲的都是图像到图像之间的映射和变换。为了处理三维图像和平面图像之间的映射,我们需要在映射中加入部分照相机产生图像过程的投影特性。这一章就是关于确定照相机的参数求解等。
针孔相机模型 图像点 p 是由图像平面与连接三维点 P和照相机中心 C 的直线相交而成的。z轴表示该照相机的光学坐标轴,由此可以得出针孔照相机的投影性质。照相机的光学坐标轴和 z 轴一致,该投影几何可以简化成相似三角形。在针孔照相机中,三维点 P 投影为图像点 p 两个点都是用齐次坐标表示的),如下所示:
照相机矩阵 其中的照相机矩阵可以进一步分解成:
内标定矩阵 K 描述照相机的投影性质,也就是内参矩阵,该矩阵仅与照相机自身情况相关,通常是以如下方式表示:
图像平面和照相机中心间的距离为焦距 f。当像素数组在传感器上偏斜的时候,需要用到倾斜参数 s。在大多数情况下,s 可以设置成 0。纵横比例参数 α 是在像素元素非正方形的情况下使用的,比如说畸变现象:径向畸变、桶状畸变、枕形畸变等。通常情况下, α默认设置为1。除焦距之外,标定矩阵中剩余的唯一参数为光心(有时称主点)的坐标 [Cx,Cy]也就是光线坐标轴和图像平面的交点。在这个例子中,唯一未知的变量是焦距 f。
另外还有相机的外参矩阵:
其中,R 是描述照相机方向的旋转矩阵,t 是描述照相机中心位置的三维平移向量。以上就是我们的主要求解的两类参数。
相机标定 照相机矩阵的分解 在已经获取到相机矩阵的情况下,我们可以逆向恢复内参数 K 以及照相机的位置 t 和姿势 R。矩阵分块操作称为因子分解。这里,我们将使用一种矩阵因子分解的方法,称为 RQ 因子分解。
def factor(self): """ 将相机矩阵分解成K、R、T """ # 分解前 3*3 的部分 K,R = linalg.rq(self.P[:,:3]) # 将 K 的对角线元素设为正值 T = diag(sign(diag(K))) if linalg.det(T) < 0: T[1,1] *= -1 self.
1、启动windows的命令窗口 快捷键windows+R,然后在输入框中输入cmd,点击确定启动命令窗口;
2、查找某一特定端口 在命令窗口中输入命令中输入netstat -ano |findstr "端口号",然后回车,就可以看到该端口被哪个程序占用
示例:netstat -ano |findstr "62001",此处注意使用的是英文输入法的引号;
3、查找端口号对应的进程名称 使用命令tasklist |findstr "进程id号",
示例:tasklist |findstr "15936",此处注意使用的是英文输入法的引号;
4、查找所有端口号的使用列表 输入命令netstat -ano然后回车,就可以看到当前启动应用的所有的端口使用列表。
5、杀掉进程 在命令框中输入taskkill /f /t /im "进程ID或者进程名称",
示例:taskkill /f /t /im "15936" ,此处注意使用的是英文输入法的引号;
或者 taskkill /f /t /im "nox_adb.exe",此处注意使用的是英文输入法的引号;
————————————————
版权声明:本文为CSDN博主「zhuangwei_8256」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zhuangvi/article/details/109697554
1、介绍 linux系统时钟有两个:
硬件时钟:即BIOS时间,就是CMOS设置时看到的时间系统时钟:linux系统Kernel时间 当Linux启动时,系统Kernel会去读取硬件时钟的设置,然后系统时钟就会独立于硬件运作。有时我们会发现系统时钟和硬件时钟不一致,因此需要执行时间同步。
2、硬件时钟 查看硬件时钟命令
hwclock --show 设置硬件时间
hwclock --set --date="09/18/18 10:35:25" 3、系统时间 查看系统时间
date 设置系统时间
date -s 2019/06/12 21:10:12 安装ntp软件同步网络时间
yum -y install ntp ntpdate -u ntp.api.bz -u:从man ntpdate中可以看出-u参数可以越过防火墙与主机同步
ntp常用服务器:
中国国家授时中心:210.72.145.44NTP服务器(上海) :ntp.api.bz 同步系统时钟和硬件时钟 重启服务器(不推荐)通过命令 硬件时钟与系统时钟同步:
hwclock --hctosys 或者 clock --hctosys 上面命令中,–hctosys表示Hardware Clock to SYStem clock。
系统时钟和硬件时钟同步:
hwclock --systohc 或者 clock --systohc
样品名称 医用血管造影X射线机 型号规格 Artis zee Ⅲ ceiling 软件:VD11
检验报告首页样品描述照片和说明关键元器件清单绝缘图绝缘路径及电介质强度试验常温性能试验(PTR的第二章)GB9706.1-2020标准进行检验GB9706.103-2020标准进行检验GB9706.228-2020标准进行检验GB9706.243-2021标准进行检验GB9706.254-2020标准进行检验按YY 1057-2016标准进行检验(Ftsw., Artis table, mono, plug-in型脚踏开关)环 境 试 验 报 告:PTR的环境试验表格下面标注了环境试验需要测试的PTR部分,总共有13个不同的试验条件,测试的部分是相同的,表格可以重复使用。
内容讲解: 介绍: Stream相当于一个数据渠道,用于操作集合、数组等多种数据源所生成的元素序列
注意:
1、Stream 自己不会存储元素。
2、Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
3、Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
Stream流步骤: (1)创建 Stream:一个数据源(如:集合、数组),获取一个流;
(2)中间操作:一个中间操作链,对数据源的数据进行处理;
(3)终止操作(终端操作):一旦执行终止操作,就执行中间操作链,并产生结果。之后,不会再被使用;
详细步骤及API解读: 步骤一:创建操作,Stream实例化
1)1)方式一:通过集合
Collection 接口被扩展,提供了两个获取流 的方法:
default Stream<E> stream() : 返回一个顺序流default Stream<E> parallelStream() : 返回一个并行流 举例:Stream<Employee> stream = employees.stream();
2)方式二:通过数组
Arrays 的静态方法 stream() 可以获取数组流: static <T> Stream<T> stream(T[] array): 返回一个流 举例:
IntStream stream = Arrays.stream(arr);
Stream<Employee> stream = Arrays.stream(arr);
3)方式三:通过Stream的of()
可以调用Stream类静态方法 of(), 通过显示值创建一个 流。它可以接收任意数量的参数。
public static<T> Stream<T> of(T... values) : 返回一个流 4)方式四:创建无限流(了解,用得少)
可以使用静态方法 Stream.iterate() 和 Stream.
第一步:
先下载好分享给大家的文件包:批量移动文件至指定文件夹.rar,将里面的.bat文件解压出来备用(批量移动文件至指定文件夹.bat )
第二步:
将批量移动文件至指定文件夹.bat 及 所有需移动至指定文件夹的文件放在同一个文件夹里,选中批量移动文件至指定文件夹.bat 右键编辑,按文档中的格式,处理好文件名 及 对应文件夹,可借助excel批量处理,保存,关闭。
第三步:
双击批量移动文件至指定文件夹.bat,即可完成批量移动指定文件至指定文件夹。
下载地址:(访问密码: 5281)
批量移动文件至指定文件夹:https://url59.ctfile.com/f/17932959-584474833-e08fa5?p=5281
前两篇内容概述了Weihua Hu*, Bowen Liu*图神经网络预训练的方法,以及context prediction进行预训练的实施代码。
context prediction 学习的图内的原子/边信息的表征,并没有包括图层面的信息。
这一部分的监督学习,是图层次的监督学习,目的是把图层面的信息增加到图的表征向量G(h)中。经过图层次的监督学习,得到的模型就可以直接用于下游的任务。
文章方法:在节点层面预训练的模型后加上一个简单的线性模型,用于图层面的监督训练
网络结构如下图:
在文献中,作者的图层面任务的监督学习是多任务学习的方法,使用chembl_filtered数据集。再经过这一层训练以后,往往还加上Fine-tuning,也就是特定任务的训练,例如:BBBP。
但是由于版本问题,chembl_filtered数据集无法加载。所以这里使用esol和lipophilicity等数据集,直接作为Supervised pre-training和Fine-tuning。
以下为代码部分:
一、导入相关包 导入相关包 import pandas as pd from tqdm import tqdm import numpy as np import os import math import random import torch import torch.optim as optim torch.manual_seed(0) np.random.seed(0) from rdkit import Chem from rdkit.Chem import Descriptors from rdkit.Chem import AllChem from rdkit import DataStructs from rdkit.Chem.rdMolDescriptors import GetMorganFingerprintAsBitVect import torch.nn.functional as F from torch_geometric.data import Data from torch_geometric.
最近因为自己的服务器重新搭建了,就想把一些好用的东西全部都用起来,就比如现在搞的这个GitHub Action自动化部署过功能。在这之前我就自己去尝试用过github上面的一个webhooks的钩子的工具,用于监听代码的push,从而实现远程服务器上的项目更新并打包,但是这总方法总的来时还是比较繁琐的,需要用pm2一直运行并监听端口,所以这次就打算使用github action来实现代码的自动化部署。
1. 选取或新建一个项目 2. 点击Actions 点击actions后会出现让你选择支持的服务,比如我这边是一个前端项目,我就选择node.js
选择完构建工具后,就会在项目的根目录下生成一个.github/workflows/node.js.yml的文件,它默认会提供给你一个模版。
这个时候我们可以根据自己的需求去修改里面的内容。
3. 了解yml文件中各个字段的含义和其作用。 有权威点的可以先参考阮一峰 GitHub Actions入门教程,了解一下Github Action。
我们来看看Github Action配置文件的基本构成,配置文件格式是.yml,示例如下:
# main.yml # 一个 workflow,名字为Github Action Example name: Github Action Example # 触发 workflow 的事件 on: push: # 分支随意 branches: - master # 一个workflow由执行的一项或多项job jobs: # 一个job任务,任务名为build build: # runs-on 指定job任务运行所需要的虚拟机环境(必填字段) runs-on: ubuntu-latest # steps是每个Job的运行步骤,可以包含一个或多个步骤 steps: # action命令,切换分支获取源码 - name: Checkout # 使用action库 actions/checkout获取源码 uses: actions/checkout@master # action命令,安装Node10 - name: use Node.
spring 源码解读-FactoryBean与BeanFactory 一、概述
在Spring中,有两个容易混淆的类:FactoryBean与BeanFactory
BeanFactory:bean工厂,是一个工厂,是IOC容器最顶层的接口,它的作用是管理bean,包括实例化、资源定位、配置对象以及建立对象之间的依赖。FactoryBean:是工厂bean,是一个bean,它的作用是产生特定bean的实例,通常这种bean没有特殊要求,仅需要提供一个工厂方法,来生成返回bean的实例, bean不需要自己实现工厂模式,Spring容器担任工厂角色,特殊情况下,其作用是产生其代理的bean。可以使用转义符**&**,来得到FactoryBean本身 BeanFactory与ApplicationContext区别?
ApplicationContext是BeanFactory的子接口,ApplicationContext提供了更完善的功能
支持国际化(继承MessageSource)统一的资源文件访问方式同时加载多个配置文件提供了监听器中注册bean的事件载入了多个上下文(父子容器),比如web层 区别点:
6. BeanFactory是延迟加载形式来注入bean,只有在getBean才对bean()进行实例化,这样无法发现对应的配置问题(getbean()方法才会抛出异常)
7. ApplicationContext在容器启动时一次性创建了所有的bean(单例),这样在容器启动的时候就可以发下配置问题,有利于检查依赖是否注入。
8. 相对于BeanFactory(一般编程的方式创建),ApplicationContext(声明的方式创建)唯一的不足就是占用内存空间,如果配置bean较多程序启动慢。
9. 两者都支持BeanPostProcessor,BeanFactoryPostProcessor的使用,区别在于BeanFactory需要手动注册,ApplicationContext是自动注册。
二、FactoryBean源码
public interface FactoryBean<T> { //获取容器管理的实例对象 T getObject() throws Exception; //获取容器管理对象的类型 Class<?> getObjectType(); //工厂创建的实例对象是否单例 boolean isSingleton(); } AbstractBeanFactory的getBean()方法 调用的就是FactoryBean,之前分析Ioc容器实例化Bean并进行依赖注入过程时,getBean()方法触发容器实例化bean的时候,调用AbstractBeanFactory 的 doCreateBean()方法来进行实例化。
getBean()--->doGetBean()--->createBean()--->doCreateBean() 获取bean实例对象的getObjectForBeanInstance()方法中,会调用FactoryBeanRegistrySupport类的getObjectFromFactoryBean()方法。改方法实现了bean工厂生成bean实例对象。
三、AbstractBeanFactory 生成bean实例对象
真正的的是FactoryBean接口调用其实现类中getObject()方法,来实现bean对象创建的功能。
工厂bean的实现类有很多,比如Proxy、JNDI、RMI、ServletContextFactoryBean,FactoryBean接口为Spring容器提供了很好的封装机制,具体的getObject由子类去实现(根据不同的实现策略)。
以后有时间自己搭一个,先马住
Web host主机:连接网站的服务器,有超级简单的构造Bluehost,更强的管控Digital Ocean
注册自己的domain name:Namecheap、Google Domains
博客网站:WordPress
其中WordPress preinstalled with your Bluehost account。
在Digital Ocean上安装WordPress比较麻烦:first need to install and configure a web server (apache or nginx);install a MySQL database and configure it correctly for WordPress;manually install and configure WordPress。Check this article out if you want to install WordPress on Digital Ocean the easy way。
设置WordPress的主题和插件:I highly recommend Divi。Install the Code Prettify plugin to your WordPress。
设计logo和图标:Fiverr、99Designs
视频链接:https://www.bilibili.com/video/BV1a34y167AZ?p=1
一、初识node.js 1.浏览器中的 JavaScript 运行环境 2.Node.js 中的 JavaScript 运行环境 3.Node.js 可以做什么 Node.js 作为一个 JavaScript 的运行环境,仅仅提供了基础的功能和API。然而,基于Node.js 提供的这些基础能,很多强大 的工具和框架如雨后春笋,层出不穷,所以学会了Node.js ,可以让前端程序员胜任更多的工作和岗位:
① 基于 Express 框架(http://www.expressjs.com.cn/),可以快速构建Web 应用
② 基于 Electron 框架(https://electronjs.org/),可以构建跨平台的桌面应用
③ 基于 restify框架(http://restify.com/),可以快速构建API 接口项目
④ 读写和操作数据库、创建实用的命令行工具辅助前端开发、etc… 4.Node.js 怎么学 浏览器中的 JavaScript 学习路径:
JavaScript 基础语法 + 浏览器内置 API(DOM + BOM) + 第三方库(jQuery、art-template 等)Node.js 的学习路径:
JavaScript 基础语法 + Node.js 内置 API 模块(fs、path、http等)+ 第三方 API 模块(express、mysql等) 二、fs 文件系统模块 2.1 什么是 fs 文件系统模块 2.2 读取指定文件中的内容 2.3 向指定的文件中写入内容 2.
首先linux中大部分命令在git中都可以使用,比如echo,pwd,ps,touch,mkdir等等
常用命令
#:代表注释
//创建初始化名字和邮箱
git config --global user.name #你的名字
git config --global user.email #你的邮箱
//创建本地仓库
git init #在一个项目里创建仓库,有.git目录出现
git init master #创建一个目录为master的本地仓库,里面包含.git目录
//添加到缓存仓库中(.git文件中)
git add #文件名
git add -A
//提交
git commit -m 文件名
git commit -A
//显示状态命令
git status #查看当前文件的所属状态
//日志命令
git log #显示你操作的文件的一些改变
//改变文件内容后撤销(未提交)
git checkout -- .
//查看文件改变内容
git diff
//提交(到本地仓库)后版本回退
git reset hard HEAD^ #文件名
git reset hard HEAD~2 #(代表上两个)
git reset hard #加上前⑦位版本号(git log可以查看) //解决文件名乱码问题
SELECT t.COLUMN_NAME,COMMENTS FROM user_col_comments t WHERE table_name='表名' SELECT t.COLUMN_NAME,COMMENTS FROM user_tab_columns t WHERE table_name='表名' SELECT *from user_tab_columns WHERE table_name='表名' user_tab_columns:查看数据库中每张表的含义注释 user_col_comments:查看表中每个字段的含义注释
申请接口 1、网上数据源网站很多,随便选一个点击进入聚合数据官网
2、点击API,然后选择【免费接口大全】,可以看到这里有许多我们Android项目用到的接口,比如天气预报、星座运势、新闻头条、历史上的今天、老黄历等等。
3、比如说,我们想申请一个API,就直接点击立即申请即可,每个接口次数都是有限制的,限量每天100次。
4、我们申请完了之后,点右上角的【个人中心】,然后【数据中心】——>【我的API】,可以看到我们的key值,这样就可以在代码中进行请求了。
使用接口 1、天气预报,直接在URLUtils.java中直接换掉天气预报的key值即可,其他不用变:
public class URLUtils { public static final String KEY = "天气预报的key值"; public static String temp_url = "http://apis.juhe.cn/simpleWeather/query"; public static String index_url = "http://apis.juhe.cn/simpleWeather/life"; public static String getTemp_url(String city){ String url = temp_url+"?city="+city+"&key="+KEY; return url; } public static String getIndex_url(String city){ String url = index_url+"?city="+city+"&key="+KEY; return url; } } 2、中华字典,也是在URLUtils.java中进行修改,这里有两个key,一个是字典的key,还有一个是成语的key:
public class URLUtils { public static String pinyinurl = "http://v.juhe.cn/xhzd/querypy?key="; public static String bushourul = "
即状态+动作==》下一个状态+动作
并再其中处理该过程的函数中,改变状态和做出响应
以上门禁闸机模型:
闸机有两个状态:lock,unlock
每个状态有两个动作:card(刷卡),pass(试图通过)
进一步分析:
lock+card:闸机状态==.unlock
lock+pass:警告,不能通过
unlock+card:感谢(已经刷卡,可以通过)
unlock+pass:通过之后,闸机状态==》lock
#include <iostream> using namespace std; typedef struct _machine machine; typedef struct _machine_state machine_state; machine_state *lock,*unlock; //状态类:有两个动作 typedef struct _machine_state{ void (*card)(machine *M); void (*pass)(machine *M); }machine_state; //机器 typedef struct _machine { void use_card(){printf("use card:");this->ms->card(this);} void try_pass(){printf("try pass:");this->ms->pass(this);} machine_state *ms; }machine; //以下定义四个 状态+动作==》下一个状态+动作 void locked_card(machine *M)//state=lock,action=card { M->ms=unlock; printf("open\n"); } void locked_pass(machine *M) { printf("alarm:you cant pass"); /* 执行 alarm 动作,调用 alarm 函数 */ } void unlocked_card(machine *M) { printf("
异常处理 常见的异常:除0溢出,数组下标越界,所要读取的文件不存在,空指针,内存不足等等。c++的异常一旦抛出,如果不捕获,则程序直接退出。c语言通过返回值判断,但有缺陷:1.容易忽略。2.容易和正常值混淆。 abort()函数 向标准错误流(cerr使用的错误流)发送消息:abnormal program termination(程序异常终止),然后终止程序。也可以使用exit()。 异常机制 抛出异常:throw xxx;将可能有异常的代码放在try{}中,然后用catch(抛出的异常类型){} 接收抛出的异常。可以用catch(…){} 接收任何类型的异常。例子: int myDiv01(int a,int b) { if(b==0) throw 0;//抛出异常 return a/b; } void test02( ) { try{ int ret = myDiv01(10, -10) ; cout<<"ret = "<<ret<<endl; } catch(int e)//只不过抛出的异常是int类型 { cout<<"捕获到int类型异常e = "<<e<<end1 ; } } 抛出指定类型的异常: //只能抛出int char 异常 void testFunc02() throw(int,char) { throw 3.14f ; } / /函数不抛出任何异常 void testFunc03() throw() { throw 10; } 返回错误码 栈解旋(unwinding) 异常被抛出后,从进入try块起,到异常被抛出前,这期间在栈上构造的所有对象都会被自动析构。 void test03( ) { try{ Person ob1("
对组 将一对值组成一个值,这一对值可以有不同的数据类型,两个值可以用pair的公有属性:first和second访问。创建对组:
应用:
set容器 所有元素会根据元素的键值自动排序。set容器的元素既是键值又是实值。不允许拥有两个相同的键值。不能通过迭代器更改元素,它是只读迭代器。因为会破坏排序规则。可以删除、插入。 set构造函数 set<T> st; //set默认构造函数: multiset<T> mst; //multiset默认构造函数: set(const set &st) ;//拷贝构造函数 set赋值操作 set& operator=(const set &st);//重载等号操作符 swap(st);//交换两个集合容器 set大小操作 size();//返回容器中元素的数目 empty() ;//判断容器是否为空 set插入和删除操作 insert(elem) ;//在容器中插入元素。 clear() ;//清除所有元索 erase(pos) ;//删除pos迭代器所指的元素,返回下一一个元素的迭代器。 erase(beg,end) ;//删除区间[beg, end)的所有元素,返回下一一个元素的迭代照 erase(elem) ; //删除容器中值为elem的元素 例子: void test01 ( ) { set<int> S ; //set容器白动根据键值排序 s. insert(30) ; S. insert(10) ; s. insert(20) ; s. insert(50) ; S. insert(40) ; for_each(s.begin() ,s.end() ,[](int val) {cout<<val<<" ";}) ; cout<<endl ; } //删除起始位置的元素 s.
功能 扩展函数的参数接口,将自适应二元函数转换为自适应一元函数。 二元适配器 ”元“指仿函数中的参数个数。val是for_each提供 tmp适配器1: bind2nd 或bind1st绑定参数适配器2:公共继承binary_ function(二元)适配器3:参数的萃取适配器4: 对operator( )进行const修饰 class MyPrint:public binary_function<int, int,void> { public : void operator() (int val,int tmp) const { cout< <val+tmp<<" "; } }; for_each(v.begin(),v.end() ,bind2nd (MyPrint() ,1000)) ; cout<<endl; bind2nd 或bind1st绑定 bind2nd:将外界数据绑定到MyPrint中的第二个参数tmp。bind1st:将外界数据绑定到MyPrint中的第一个参数val。 cout<<"bind2nd"<<endl; for_each(v.begin(),v.end() ,bind2nd(MyPrint(),1000) ) ; cout< <end1 ; cout<<"bind1st" for_each(v.begin(),v.end() ,bind1st(MyPrint() ,1000) ) ; cout< <endl ; 一元取反适配器(not1) 找出第一 一个小于3的数取反适配器1 : not1修饰取反适配器2: public unary_function(一元)取反适配器3: 参数萃取取反适配器4: const修饰operator () class MyGreaterThan3:public unary_ function<int,bool> { public: //一 元谓词 bool operator()(int val)cqnst { return val>3; } } ret = find_ _if(v.
函数对象是类似于函数的对象,可以是类对象或函数指针(包含函数名,因为函数名被用作指针)。 谓词 返回值类型为bool的普通函数或仿函数叫谓词。如果普通函数有一个参数,叫一元谓词,有两个参数,叫二元谓词。 一元谓词 //普通函数作为一元谓词 bool greaterThan20(int val) { return val>20 ; } //仿函数作为一元谓词 class MyGreaterThan20 { public: bool operator()(int val) { return val>20; } } for_each(v. begin() ,v.end(),[](int val){cout<<val<<" ";}) ; cout< <endl; //需求:找出第一个大于20的数 vector<int>: : iterator ret; //普通函数完成 //ret = find_ if(v. begin() ,v.end(),greaterThan20) ; ret = find_if(v.begin() ,v.end(),MyGreaterThan20()) ; if(ret != v.end() ) { cout<<"第一个大 于20的数为:"<<*ret<<endl ; } 二元谓词 //普通函数作为-元谓词 bool myGreater(int v1,int v2) { //为啥从大到小排序 return v1>v2; //仿函数作为二元谓词 class MyGreater { pubVfc: bool operator() (int vl, int v2 ) { return v1>v2 ; } } //从大-->小排序 //sort(v.
手把手教你一整套R语言数据分析+建模流程 Intro项目背景前期准备数据描述数据清洗预分析及预处理数值型数据类别型数据 特征建模模型对比 Intro 近期在整理数据分析流程,找到了之前写的一篇代码,分享给大家。这是我上学时候做的一个项目,当时由于经验不足产生了一些问题,这些问题会在之后一点一点给大家讨论,避免各位踩坑。本篇分享会带一些讲解,可能有些地方不够清楚,欢迎留言讨论。
本次除了分享之外也是对自己之前项目的一个复盘。还是使用R语言(毕竟是我钟爱的语言)。Python的如果有需求之后会放别的项目。
本篇中包含了数据导入,清洗,可视化,特征工程,建模的代码,大家可以选择需要的去参考。
所有代码+注释+数据在这里 https://download.csdn.net/download/zhaotian151/85035590
付费下载链接,觉得文章有用可以适当支持,当然你也可以从这个文章里面一个个摘代码~
不建议还在上学同学直接抄作业哦,所有的项目都是宝贵的经验,是你上班之后确确实实可以用到的东西,希望大家上学的时候好好学习。
项目背景 数据来自Online Shopper’s Intention 包含12,330 条数据, 10个计数型特征和8个类别型特征。 使用‘Revenue’ 作为标签进行建模。最终目的就是根据拿到的这些数据去建立一个可以预测Revenue的模型。
有些同学说数据被kaggle从网上删掉了,数据的csv上传到资源里了,需要可以连同代码一起购买。
前期准备 首先你要下载一个R语言以及它的舒适版本R studio。
下载方式如下:
安装R以及Rstudio
如果之前有用过R的朋友请忽略这一段。
安装R非常简单,直接官网下载
之后下载Rstudio,这个相当于R语言的开挂版,界面相比于R来说非常友好,辅助功能也很多,下载地址
#注意Rstudio是基于R语言的,需要下载安装R语言后才可以安装使用。
安装好了后运行以下代码来导入package们。
setwd("~/Desktop/STAT5003/Ass") #选择项目存放的位置,同样这也是你数据csv存放的位置 # install.packages("xxx") 如果之前没有装过以下的包,先用这句话来装包,然后再去load # the following packages are for the EDA part library(GGally) library(ggcorrplot) library(psych) library(ggstatsplot) library(ggplot2) library(grid) # the following packages are for the Model part library(MASS) library(Boruta) # Feature selection with the Boruta algorithm library(caret) library(MLmetrics) library(class) library(neuralnet) library(e1071) library(randomForest) library(keras) 导入的包有些多,keras那个的安装可以参考我之前的文章 (R语言基于Keras的MLP神经网络详解
简单工厂模式 属于类的创建型模型,又叫静态工厂方法模式。定义一个类来负责创建其他类的实例,被创建的实例通常具有共同的父类。 #include<iostream> #include<string> using namespace std; //简单工厂模式: class Phone { public: virtual void show_name() { cout << "我是手机!\n\n"; } }; class iQOO_phone: public Phone { public: virtual void show_name() { cout << "我是iQOO手机!\n\n"; } }; class Vivo_phone: public Phone { virtual void show_name() { cout << "我是vivo手机!\n\n"; } }; class Factory { public: Phone* creat(string name) { if (name == "iQOO") { cout << "开始生产iQOO手机!\n\n"; return new iQOO_phone; } if (name == "
文章目录 1.定义1.1 举个例子 2.平方剩余和平方非剩余的个数3.欧拉判别法3.1 例13.2 例2 1.定义 设p是奇素数(大于2的素数),如果二次同余式 x 2 = a ( m o d p ) , ( a , p ) = 1 x^2 = a(mod\ p), (a, p) = 1 x2=a(mod p),(a,p)=1 有解,则称a为模p的平方剩余(一个数的平方模p的余数),否则a称模p的平方非剩余。平方剩余和平方非剩余又称为二次剩余和二次非剩余。
1.1 举个例子 请求出11的所有二次剩余。
在解决这个问题之前,首先我们要清楚11的一个剩余系为0,1,2,3,…,10。所以11的二次剩余只可能来源于这些数。为了决定哪些整数是11的二次剩余,我们计算整数1,2,3,…,10的平方(有同学可能就要问了,为什么只计算这10个数的平方呢?因为《初等数论及其应用》中的引理11.1提到了同余方程或者无解或者有两个模p不同于的解,所以我们只需要找这10个数就可以了,那有可能同学又要问了,怎么把0给漏掉了,因为(a,p) = 1,可以打消疑虑了吧。),得到
1 2 ≡ 1 0 2 ≡ 1 ( m o d 11 ) 1^2 \equiv 10 ^2 \equiv 1 (mod \ 11) 12≡102≡1(mod 11)
2 2 ≡ 9 2 ≡ 4 ( m o d 11 ) 2^2 \equiv 9^2 \equiv 4 (mod \ 11) 22≡92≡4(mod 11)
数组 在图7-1中,从第一行开始,依次对每一行的索引从左至右连续编号,得到图7-2a所示的映射结果。它把二维数组的索引映射为[0,n-1]中的数,这种映射方式称为行主映射( row major mapping)。索引对应的数称为行主次序( row-major order)。图7-2b是另一种映射模式,称为列主映射图7-1 整型数组score [3] [6]的索引排列表( column major mapping)。在列主映射中,对索引的编号从最左列开始,依次对每一列的索引从上到下连续编号。在行主次序中,映射函数为: map(i1,i2)= i1*U2+ i2,其中u2是数组的列数。
将多维数组映射为一维数的时候,采用行主映射公式。三维数组的行主映射函数为: map(i1,i2,i3) = i1u2u3 + i2*u3 + i3C++用所谓数组的数组来表示一个多维数组。一个二维数组被表示为一个一维数组,这个一维数组的每一个元素还是一个一维数组。一个三维数组被表示为一个一维数组,这个一维数组的每一个元素是一个二维数组。 一个不规则二维数组的创建和使用 int main (void) { int numberOfRows = 5; //1定义每一行的长度 int length[5] = (6,3,4, 2,7}; //声明一个二维数组变量 //且分配所需要的行数 int **irregularArray = new int* [numberOfRows] ; //分配每一行的空间 for (int i = 0; i < numberOfRows; i++) { irregularArray[i] = new int [1ength[i]]; } //像使用规则数组一样使用不规则数组. irregularArray[2][3] = 5; irregularArray[4][6] = irregularArray[2][3] + 2; irregularArray[1][1] = 3; //输出选择的数组元素 cout << irregularArray[2][3] << endl ; cout << irregularArray[4][6] << endl; cout << irregularArray[1][1] << endl; return 0; } 矩阵 计算过程中,将二维数组转换为一维数组,利用行主映射公式。 矩阵类matrix的声明 template<class T> class matrix [ friend ostream& operator<< (ostream&, const matrix<T>&) ; public: matrix(int theRows = 0,int theColumns = 0) ; matrix(const matrix<T>&) ; ~matrix() {delete [] element; } int rows() const { return theRows; } int columns() const { return theColumns; } T& operator () (int i, int j) const; matrix<T>& operator= (const matrix<T>&) ; matrix<T> operator+ () const; matrix<T> operator+ (const matrix<T>&) const; matrix<T> operator- () const; matrix<T> operator- (const matrix<T>&) const; matrix<T> operator* (const matrix<T>&) const; matrix<T>& operator+= (const T&) ; private: int theRows, //矩阵的行数 theColumns; //矩阵的列数 T *element; //数组element }; 矩阵类 matrix的构造函数和复制构造函数 template<class T> matrix<T>::matrix (int theRows, int theColumns) { //矩阵构造函数 //检验行数和列数的有效性 if (theRows < 0 || theColumns < 0) throw illegalParameterValue("
计算机是如何执行递归函数的呢? 答案是使用递归工作栈(recursion stack)。 当一个函数被调用时,一个返回地址( 即被调函数一旦执行完,接下去要执行的程序指令的地址)和被调函数的局部变量和形参的值都要存储在递归工作栈中。当执行一次返回时,被调函数的局部变量和形参的值被恢复为调用之前的值(这些值存储在递归工作栈的顶部),而且程序从返回地址处继续执行,这个返回地址也存储在递归工作栈的顶部。 如果把数组线性表的右端定义为栈顶,那么入栈和出栈操作对应的就是线性表在最好情况下的插入和删除操作。结果两个操作的时间都为O(1)。 用链表的左端作为栈顶,需要调用的链表方法是get(0)、insert(0,theElement) 和erase(0),其中每一个链表方法需要用时0(1)。分析表明,我们应该选择链表的左端作为栈顶。 括号匹配 通过观察可以发现,如果从左至右地扫描一个字符串,那么每一个右括号都与最近扫描的那个未匹配的左括号相匹配。这种观察结果促使我们在从左至右的扫描过程中,将扫描到的左括号保存到栈中。每当扫描都一个右括号,就将它与栈顶的左括号(如果存在)相匹配,并将匹配的左括号从栈顶删除。 void printMatchedPairs(string expr) { //括号匹配 arrayStack<int> s; int length = (int) expr.size() ; //扫描表达式expr寻找左括号和右括号 for (int i = 0; i < length; i++) { if (expr.at(i) == '(') s.push(i); else if (expr.at(i) == ')') { try {//从栈中删除匹配的左括号 cout << s.top() << ' ' << i << endl; s.pop() ; } //没有栈匹配 catch (stackEmpty) {//栈为空。没有匹配的左括号 cout << "No match for right parenthesis"
虽然在n个元素的有序数组上折半查找所需要的时间为O(logn),但是在有序链表上查找所需要的时间为O(n)。为了提高有序链表的查找性能,可以在全部或部分节点上增加额外的指针。在查找时,通过这些指针,可以跳过链表的若千个节点,不必从左到右连续查看所有节点。增加了额外的向前指针的链表叫做跳表(skiplist)。它采用随机技术来决定链表的哪些节点应增加向前指针,以及增加多少个指针。基于这种随机技术,跳表的查找、插入、删除的平均时间复杂度为O(logn)。然而,最坏情况下的时间复杂度却变成O(n)。散列是用来查找、插入、删除的另一种随机方法。与跳表相比,它把操作时间提高Θ(1),但最坏情况下的时间仍为Θ(n)。C++的STL中使用了散列的容器类有: hash_ map、hash_multimap、hash_ multiset、 hash_ set。 有序数组、有序链表、跳表和哈希表的渐近性能汇总 字典 抽象类dictionary template<class K,class E> class dictionary { public: virtual ~dictionary() {} virtual bool empty() const = 0; //返回true, 当且仅当字典为空 virtual int size() const = 0; //返回字典中数对的数目 virtual pair<const K,E>* find(const K&) const = 0; //返回匹配数对的指针 virtual void erase (const K&) = 0; //删除匹配的数对 virtual void insert (const pair<const K,E>&) = 0; //往字典中插入一个数对 }; 线性表描述 sortedChain的节点是pairNode的实例。pairNode 的实例有两个域:element 和next, 它们的类型分别是 pair<const K,E> 和 pairNode<K,E>*。 方法sortedChain<K,E>::find template<class K,class E> pair<const K,E>* sortedChain<K,E>:: find(const K& theKey) const {//返回匹配的数对的指针 //如果不存在匹配的数对,则返回NULL pairNode<K,E>* currentNode = firstNode; //搜索关键字为theKey的数对 while (currentNode !
相关内容:
linux嵌入式软件中libmudbus库的移植与使用(一)
linux嵌入式软件中libmudbus库的移植与使用(二)
Modbus RTU与Modbus TCP的区别
Modbus通信协议具有多个变种,支持串口(主要是RS-485总线),以太网多个版本,其中最著名的是Modbus RTU,Modbus ASCII
和Modbus TCP三种。在工业现场一般都是采用Modbus RTU协议,一般大家说的基于串口通信的Modbus通信协议都是指Modbus RTU通信协议。
与Modbus RTU协议相比较,Modbus TCP协议则是在RTU协议上加一个MBAP报文头,并且由于TCP是基于可靠连接的服务,RTU协议中的
CRC校验码就不再需要,所以在Modbus TCP协议中是没有CRC校验码的,所以就常用一句比较通俗的话来说:Modbus TCP协议就是
Modbus RTU协议在前面加上五个0以及一个6,然后去掉两个CRC校验码字节就OK。虽然这句话说得不是特别准确,但是也基本上把RTU与TCP
之间的区别说得比较清楚了。
Modbus的功能码有:
功能码含义功能码含义0x01读线圈0x04读输入寄存器0x05写单个线圈0x03读保持寄存器0x0F写多个线圈0x06写单个保持寄存器0x02读离散量输入0x10写多个保持寄存器 一、Modbus RTU
RTU协议中的指令由地址码(一个字节),功能码(一个字节),起始地址(两个字节),数据(N个字节),校验码(两个字节)五个部分组成。
数据由数据长度(两个字节,表示的是寄存器个数,假定为M)和数据正文(M乘以2个字节)组成。
发:01 03 01 8E 00 04 25 DE //读(0x03),从寄存器地址01 8E 开始读,读4个寄存器00 04
回:01 03 08 00 01 00 01 00 01 00 01 28 D7 // 08表示数据长度 ,00 01 00 01 00 01 00 01读到的数据
发:00 10 00 20 00 01 02 00 00 AC A0 // 写(0x10),从寄存器地址 00 20开始写,写一个寄存器 00 01,写入值 00 00
目录 [Problem 9305](https://xjoi.net/problem/9305) 加法检测器一 题目内容二 新知识点三 思路四 AC代码 [Problem 3537](https://xjoi.net/problem/3537) 判断闰年一 题目内容二 新知识点三 思路四 AC代码 [Problem 3903](https://xjoi.net/problem/3903) 水仙花数一 题目内容二 新知识点三 思路四 AC代码 [Problem 9304](https://xjoi.net/problem/9304) maoge的数学测试二 新知识点2.1 在一行内写下一句if(if-else if-else,if-else if,if-else)语句 三 思路四 AC代码 [Problem 1111](https://xjoi.net/problem/1111) 三数中最大和最小一 题目内容二 新知识点三 思路四 AC代码 [Problem 9873](https://xjoi.net/problem/9873) 从大到小一 题目内容二 新知识点三 思路四 AC代码 Problem 9305 加法检测器 一 题目内容 【题目描述】
maoge在教小Maoge加法,他想计算出小Maoge加法的准确度如何,但是因为题目太多了,他算不出来,所以找到了你。
【数据格式】
输入一行三个数a,b,c,分别表示两个加数和小Maoge算出来的答案(a,b,c在0~10000之间)。
输出一行一个字符串。
如果小Maoge算的答案和正确答案的差值在正负10(不包括10)以内,就输出“Good”。
如果在10~20(包括10不包括20)之间,就输出“not bad”
否则输出“QwQ”。
样例输入:
12 35 37
样例输出:
not bad
二 新知识点 本题没有新知识点。
1.连接MySQL数据库 2.创建一个数据库类 //引用命名空间 using MySql.Data.MySqlClient; //数据库类 class SQLDemo{ MySql.Data.MySqlClient.MySqlConnection conn;//一个连接对象 //数据库连接方法 public MySqlConnection Connection() { //创建一条string语句 string connestStr = "data source = localhost; uid = 用户名; password = 密码; database =数据库;"; //连接到数据库 MySql.Data.MySqlClient.MySqlConnection conn = new MySql.Data.MySqlClient.MySqlConnection(connestStr); conn.Open();//打开数据库 this.conn = conn; return conn; } //关闭数据库 public void Close() { this.conn.Close(); } //返回数据库MySqlCommand类型,对应数据库后续的操作 public MySqlCommand Command(string sql) { //将SQL以及链接对象作为参数传入 MySql.Data.MySqlClient.MySqlCommand cmd = new MySql.Data.MySqlClient.MySqlCommand(sql, conn); MySql.Data.MySqlClient.MySqlDataAdapter sda = new MySql.Data.MySqlClient.MySqlDataAdapter(); //向数据库发送查询语句 sda.
近几年,不少车企纷纷推出智能车型,落地L2~L4等级的辅助驾驶技术,提供自动泊车、自动巡航、低速自动驾驶功能;另外还有许多机构在无人车、自动驾驶船舶等领域取得不错的研究成果。
这些都得益于“自动驾驶”技术的发展,为智能交通创造了更多的可能。
在自动驾驶系统中,激光雷达作为环境感知设备,其采集的点云数据对三维目标检测、反馈周围是否有障碍物、距离前车有多远等起着重要作用。
下面给大家具体介绍一下。
01 什么是激光雷达点云数据 激光雷达(LiDAR)点云数据,是由三维激光雷达设备扫描得到的空间点的数据集,每一个点都包含了三维坐标信息,也是我们常说的X、Y、Z三个元素,有的还包含颜色信息、反射强度信息、回波次数信息等[1]。
点云信息示意(图源:网络)
它们是如何产生的呢?
02 激光点云数据的采集方式 激光点云数据,由车载激光扫描系统向周围发射激光信号,然后收集反射的激光信号得来的,再通过外业数据采集、组合导航、点云解算,便可以计算出这些点的准确空间信息。
看上去一个简单的数据获取,其实包含了较为复杂的设备结构及数据采集过程。
一种典型的激光雷达传感器系统组成(图源:参考资料[2])
比如,就车载激光扫描系统而言,包括了激光扫描仪、CCD相机、惯性测量装置(IMU)、里程计(DMI)、全球定位系统(GPS)、计算机及控制单元等。
另外,由于三维激光雷达传感器的系统结构特点与工作原理,使其具有固定范围的水平视角和垂直视角,所以在数据采集、分析过程中,需要对水平分辨率和垂直分辨率进行分析,考虑每个数据点之间的距离精度,根据结果为后续点云数据处理方法的相关参数提供设置参考[2]。
KITTI点云数据预览效果(图源:参考资料[3])
03 三维激光点云数据特点 三维激光雷达传感器采集的场景点云数据,一般具有以下典型的特征[2]:
1. 稀疏性
与固定尺寸的二维图像中固定的像素数量截然不同,三维激光点云本质上是一种低分辨率的离散化采样,此外,环境场景的不同也会导致固定线数的激光雷达采集到的不同数量的点,这些均导致了点云数据固有的稀疏性。
2. 无序性
与二维图像的像素排列严格有序不同,点云数据是无序的向量的集合,其中的点不具有固定的排列顺序,任何一种排序组合的方式进行输入描述,其代表的都是同一组点云数据。
3. 空间分布不均匀
随着检测距离的增加,具有固定水平和垂直角度分辨率的激光雷达的距离检测精度在不断降低。具体表现为距离激光雷达传感器越近的物体,其表面被采集的点的数量就越多,其对应的点云也就越稠密,反之,距离越远,对应的点云也越稀疏。
4. 表示信息的有限性
由于场景中三维物体的自遮挡,使得激光雷达只能检测到三维物体的一部分表面,这也导致了点云数据只能表示物体的一部分几何信息。
04 三维点云数据集 通过深度传感器如激光雷达对环境场景进行数据采集,并且进行数据标注,最后形成的一定规模的数据集。可用于自动驾驶技术领域相关算法和计算机视觉算法的验证与性能评估。比如常用的KITTI数据集。
那三维点云数据可以用来干什么?
05 三维点云数据的应用方向 三维点云在自动驾驶领域中的应用可以分为以下两个方面:
基于场景理解和目标检测的实时环境感知和处理;基于可靠定位和参考的高精度地图和城市模型的生成和构建。 06 数据集资源 OpenDataLab平台已经上架KITTI系列数据集,提供了完整的数据集信息、统一的脚本格式、流畅的下载速度,欢迎体验!
· KITTI2012 https://opendatalab.com/datasets/66
· KITTI Tracking https://opendatalab.com/datasets/129
· KITTI Object https://opendatalab.com/datasets/130
· KITTI Flow 2015 https://opendatalab.com/114
· KITTI Flow 2012 https://opendatalab.com/160
· KITTI Scene Flow 2015 https://opendatalab.
webpack 家喻户晓耳熟能详的前端编译工具在经历这么久的磨练后也开始显现出自己的颓势
繁重的编译过程缓慢的加载及打包因为依赖node.js每次编译都要进行繁琐的递归去构建依赖图谱,导致热更新效率低下 vite 新一代的前端开发和构建工具强大的拥有强大的编译及高效的处理能力
build
webpack打包过程
1.识别入口文件
2.通过逐层识别模块依赖。(Commonjs、amd或者es6的import,webpack都会对其进行分析。来获取代码的依赖)
3.webpack做的就是分析代码。转换代码,编译代码,输出代码
4.最终形成打包后的代码
webpack 打包原理
1.先逐级递归识别依赖,构建依赖图谱
2.将代码转化成AST抽象语法树
3.在AST阶段中去处理代码
4.把AST抽象语法树变成浏览器可以识别的代码, 然后输出
因为需要递归识别依赖,构建依赖图谱。图谱对象就是类似下面这种
{ './app.js': { dependencies: { './test1.js': './test1.js' }, code:'"use strict";\n\nvar _test = _interopRequireDefault(require("./test1.js"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }\n\nconsole.log(test 1);' }, './test1.js': { dependencies: { './test2.js': './test2.js' }, code: '"use strict";\n\nvar _test = _interopRequireDefault(require("./test2.js"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "
AndroidStudio相机拍照或从相册中选取照片并显示 本文最大优点在于适配Android8系统,项目给的平板版本很低,系统适配折磨了我很久
找了很多方法,这个版本是最简单并且可以成功运行的
0.AndroidMainfest.xml以及build.gradle配置文件 主要是添加权限uses-permission和provider,这些是必须添加的
provider根据自己的项目结构自行改,可以在后面写完file_paths.xml之后再写进来
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.buildmaterialapplication"> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" tools:ignore="ProtectedPermissions"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.CAMERA"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.MyApplication"> <activity android:name=".MainActivity" android:exported="true" tools:ignore="DuplicateActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <provider android:authorities="com.buildmaterialapplication.fileprovider" android:name="androidx.core.content.FileProvider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths"/> </provider> </application> <supports-screens android:resizeable="true" /> </manifest> build.gradle我不确定我有没有改过。。以防万一还是放上来
plugins { id 'com.android.application' } android { compileSdk 31 defaultConfig { applicationId "
主要是因为粗心导致的
报错信息 Exception in thread “main” java.lang.RuntimeException: com.ctc.wstx.exc.WstxUnexpectedCharException: Unexpected character ‘l’ (code 108) in prolog; expected ‘<’
at [row,col,system-id]: [1,4,“file:/home/export/servers/apache-hive-3.1.2-bin/conf/hive-site.xml”]
at org.apache.hadoop.conf.Configuration.loadResource(Configuration.java:3092)
at org.apache.hadoop.conf.Configuration.loadResources(Configuration.java:3041)
at org.apache.hadoop.conf.Configuration.loadProps(Configuration.java:2914)
at org.apache.hadoop.conf.Configuration.addResourceObject(Configuration.java:1034)
at org.apache.hadoop.conf.Configuration.addResource(Configuration.java:939)
at org.apache.hadoop.hive.conf.HiveConf.initialize(HiveConf.java:5151)
at org.apache.hadoop.hive.conf.HiveConf.(HiveConf.java:5099)
at org.apache.hadoop.hive.common.LogUtils.initHiveLog4jCommon(LogUtils.java:97)
at org.apache.hadoop.hive.common.LogUtils.initHiveLog4j(LogUtils.java:81)
at org.apache.hadoop.hive.cli.CliDriver.run(CliDriver.java:699)
at org.apache.hadoop.hive.cli.CliDriver.main(CliDriver.java:683)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.hadoop.util.RunJar.run(RunJar.java:323)
at org.apache.hadoop.util.RunJar.main(RunJar.java:236)
Caused by: com.ctc.wstx.exc.WstxUnexpectedCharException: Unexpected character ‘l’ (code 108) in prolog; expected ‘<’
at [row,col,system-id]: [1,4,“file:/home/export/servers/apache-hive-3.
使用场景:在使用virtualbox创建centos7的时候忘记了root密码。需要修改密码
解决方案
1:重启centos7
2:然后按下“e”键进入编辑此选项,等待出现画面后按下键一直翻到最后。找到linux16.....ro crashdernel=auto....类似字样。
然后把ro更改为"rw init=/sysroot/bin/sh",更改完成后按下ctrl+x组合键,运行系统。如图所示:
3:待启动后,输入命令 chroot /sysroot
然后输入"passwd root",设置用户密码,两次输入相同密码
然后执行命令"touch /.autorelabel" 写入系统信息。
4 然后强制重启系统,待系统到登录界面输入更改好的密码,发现可以登录成功。
线程池 什么是线程池为什么要使用线程池线程池的工作流程图任务队列线程池的创建线程池的初始化工作者添加任务线程池的销毁完整代码threadpool.hpthreadpool.c 总结 什么是线程池 线程池就是一个容纳多个线程的容器,对于一线线程我们可以多次对此线程进行重复使用,从而省去频繁创建线程对象的操作。
为什么要使用线程池 频繁的进行进程的创建与销毁将带来很多开销。不但如此,进程间频繁的切换也将减低 CPU 的利用率。 如果能复用之前创建的进程,而不是为每个并发任务创建一个进程,能有效降低进程创建与销毁的开销并减少进程间切换,从而减少对 CPU 资源的浪费。 虽然线程创建与销毁的代价小于进程创建与销毁,隶属同一进程的线程间切换的代价也小于进程间切换,但复用之前创建的线程,也能有效降低线程创建与销毁的开销并减少线程间切换,从而减少对 CPU 资源的浪费。
当任务很多的时,我们就可以调用线程池,从而有效的的对CPU资源的浪费。
图解:
线程池的工作流程图 任务队列 我们应该以任务队列的形式存储任务,线程池中的线程只需要从任务队列中拿任务就可以了
typedef struct task { void(*run)(void*arg);//函数指针,指向一个函数(任务) void*arg; //上面指针所指向函数的参数 struct task *next; //next指针,指向下一个任务节点 }task; 这样我们就把任务队列创建好了。
线程池的创建 typedef struct threadpool { task*first; //指向任务队列的起始位置 task*end; //指向任务队列的末尾位置 int threadNUM;//线程数量 int tasksize;//任务数量 pthread_mutex_t mutexpool;//锁整个线程池 pthread_cond_t notempty;//任务队列是不是空 int shutdown;//是不是要销毁线程池,销毁为1,不销毁为0 }threadpool; mutexpool是一个互斥锁,他的作用就是,当某一个线程需要拿任务或者要修改线程池中的某个成员时,为了防止其他线程同时也在对线程池进行访问,从而导致数据错乱,我们就需要使用互斥锁,让某个线程在访问线程池的时候将线程池锁住,不让其他线程进行访问。
notempty是一个条件变量,其作用就是当任队列为空时,我们就需要拿该条件变量将线程阻塞,当有新任务添加进来时,再对线程进行唤醒。
此时我们已经创建出了线程池,我们接下来所需要实现的接口。
//初始化线程池 threadpool*threadpoolinit(int nmberu); //销毁线程池 int threadpooldestroy(threadpool*pool); //给线程池添加任务 void threadpoolAdd(threadpool*pool,void(*run)(void*),void*arg); //工作者(实现任务的实现) void*worker(void*arg); 线程池的初始化 我们所要完成的任务就是,使用malloc函数将线程在堆区创建出来,然后对线程池中的互斥锁和条件变量进行初始化时。
目录: 前言:一,查看当前目录下的文件:1.查看当前文件下文件(不包括隐藏文件):2.查看当前文件下的所有文件(不包括隐藏文件)3.查看当前目录下面的所有文件(包括隐藏文件)的详细信息4.查看指定文件内容5.查看文件路径 二,切换文件目录1.进入文件夹:2.进入根目录(返回git bash初始目录):3.返回上级目录: 三,文件操作1.创建指定名称的文件:2.删除指定文件(文件夹):3.重命名文件4.创建指定文件夹:5.打开指定文件 前言: 注意:在git bash中我们输入"\“符号时尤其需要注意,直接在路径表示中使用”\"会导致出现该文件夹不存在的错误提示!如下:
因此我们必须在路径中使用"\“或”/"符号(除非有额外的设置)!所以必须使用这两种形式的路径!
一,查看当前目录下的文件: 1.查看当前文件下文件(不包括隐藏文件): ls 2.查看当前文件下的所有文件(不包括隐藏文件) ls -a 3.查看当前目录下面的所有文件(包括隐藏文件)的详细信息 ls -a1 4.查看指定文件内容 cat <指定文件名全称:含文件类型> 5.查看文件路径 pwd 二,切换文件目录 1.进入文件夹: cd <指定的文件夹路径> 2.进入根目录(返回git bash初始目录): cd / 3.返回上级目录: cd .. 三,文件操作 注意:本文所指的文件名均包含文件类型的全称!如:test.txt
1.创建指定名称的文件: touch <指定名称的文件名(含类型)全称> 2.删除指定文件(文件夹): rm -rf <删除指定文件(文件夹)全称> 3.重命名文件 mv <原文件全称> <新全称> 注意:原文件全称与新全称要有空格
4.创建指定文件夹: mkdir <指定文件夹名称> 5.打开指定文件 start <指定文件名全称> 一些范例指令:可供大家对照!
这里写目录标题 论文详情VIT缺点改进点概述核心思想整体结构名称解释 Window、Patch、Token与vit区别结构过程Patch EmbeddingBasicLayerPatch MergingSwin Transform BlockWindow AttentionShifted Window Attention 总结SwinT模块一、SwinT模块的使用演示,接口酷似Conv2D二、使用SwinT替换Resnet50中Bottleneck中的Conv2D层,创建SwinResnet! 代码Patch EmbeddingPatch MergingMask 论文详情 名称:Swin Transformer: Hierarchical Vision Transformer using Shifted Windows
地址:原论文
代码:代码地址
视频讲解:
1李沐
2胡瀚研究员:Swin Transformer和拥抱Transformer的五个理由
3霹雳吧啦Wz-Swin-Transformer网络结构详解
笔记参考:
1李沐b站视频讲解笔记
2笔记解释
3霹雳吧啦Wz
4胡瀚研究员:Swin Transformer和拥抱Transformer的五个理由
专访 Swin Transformer 作者胡瀚:面向计算机视觉中的「开放问题
6.2021-Swin Transformer Attention机制的详细推导
7.详解Swin Transformer核心实现,经典模型也能快速调优
8.很好:理论+代码【机器学习】详解 Swin Transformer (SwinT)
swin-T模块
1.SwinT-让Swin-Transformer的使用变得和CNN一样方便快捷
VIT缺点 应用:
ViT主要针对图像分类问题设计,不适合作为通用 模型的backbone,也不适合更细粒度的识别问题(如目标检测、分割等)
vit实现过程:
ViT通过将图像均分成不相交的patch,通过编码每个patch然后计算两两patch之间的self-attention,来实现聚合信息,即聚合全局信息。
简述:直接将图片切割成相同大小的块,做全局Transformer
缺点:应对更高清的图片时,划分的patch数会受计算资源掣肘。
你可以这么想,4x4=16个patch,两两计算自注意力,和100x100=10000个patch,两两计算自注意力,计算复杂度完全不一样(前者的计算16x16次,后者计算 10000x10000 次,即计算复杂度跟 (HxW)平方呈线性关系)
改进点 目前Transformer应用到图像领域主要有两大挑战:
1一个就是尺度上的问题。
图片的scale变化非常大,非标准固定的
因为比如说现在有一张街景的图片,里面有很多车和行人,里面的物体都大大小小,那这时候代表同样一个语义的词,比如说行人或者汽车就有非常不同的尺寸,这种现象在 NLP 中就没有
通过 json_last_error() 或 json_last_error_msg(); 获取错误信息
解决方法
$response= unserialize(str_replace(array('NAN;','INF;'),'0;',serialize($response)));
1.预览效果
官网地址可以去看看里面的介绍:https://github.com/xyxiao001/vue-cropper
1.先在项目中安装一下
方法1:npm install vue-cropper 方法2:yarn add vue-cropper 2.安装成功在项目中的main.js引入
import VueCropper from 'vue-cropper' Vue.use(VueCropper) //方便我们直接用 3.我们最好把这个封装成一个组件 这样的话在其他页面都能用
组件:YUploadImg
<template> <el-dialog title="图片剪裁" width="630px" :visible.sync="dialogVisible" append-to-body> <div class="cropper-content"> <div class="cropper" style="text-align: center"> <!-- 这个组件vueCropper就是我们刚才引入在main.js里面的那个 直接拿来用 就好 --> <vueCropper ref="cropper" :img="option.img" :output-size="option.size" :output-type="option.outputType" :info="true" :full="option.full" :can-move="option.canMove" :can-move-box="option.canMoveBox" :original="option.original" :auto-crop="option.autoCrop" :fixed="option.fixed" :fixed-number="option.fixedNumber" :center-box="option.centerBox" :info-true="option.infoTrue" :fixed-box="option.fixedBox" /> </div> </div> <div slot="footer" class="dialog-footer"> <el-button> <el-upload class="avatar-uploader" list-type="picture" action="" :auto-upload="false" :show-file-list="false" :on-change="changeUpload"> <i class="el-icon-refresh" style=" margin-right: 5px;"
文章目录: 一、php基础知识 二、留言板功能实现 三、留言板效果 一 php基础知识 1、变量赋值时单引号与双引号的区别
在给字符串变量赋值的时候使用单引号时在编译时并不会识别单引号中变量,而使用双引号则会识别双引号中的变量
2、数组的增删改查
数组使用 键+值 的表达方式,键跟C语言中的数组指针类似
增:只需要定义数组新的对应下标的值就行
删:使用 unset(数组键)函数 删除某一数组元素
改:指定对应数组的元素,重新赋值即可
查:echo 数组键
3、前端数据发送与后端接受(与数组有关)
通过<form>表单中POST方式提交<input>所提交的数据时,在<input type=’text’ name=’aa’>中所定义的name属性的值相当于是自己定义数组的键,而这个数组就是POST[]数组,当提交到对应的php文件中后使用 $_POST[‘aa’] 来获取数组的值
总结一下就是在html中重新定义POST[]数组的键(注:其值有<input>中name属性决定),然后通过表单提交到对应的php文件且存储到POST[]数组中(注:最好使用POST方法,使用GET的话所提交的内容会明文传输安全性低),这样php文件就可以通过POST[]数组这个桥梁来获得前端所提交的数据。(奈斯!以前只知道使用,不知道原理)
4、字符串、变量的拼接
在php中使用点号“ . ”进行结果的拼接而不是加号
众所周知单引号内是字符串,但是若该字符串是数字的话php使用加号时就变成了运算
而使用点号时就会达到拼接效果
5、die(“信息”)函数
执行到此语句后停止执行程序并且可以打印出信息,感觉跟echo语句差不多
6、foreach()函数
foreach(数组名 as $key => $value)
对数组进行遍历会遍历出数组关键字赋值给key及取值赋值给value
foreach(数组名 as $value)函数
对数组进行遍历会遍历出数组的值赋值给value
7、php中的全局变量与局部变量
全局变量:函数之外定义的变量
局部变量:函数内部定义的变量
规则:全局变量只能在函数之外使用,函数内部无法使用,同理,局部变量只能在函数内部使用,函数之外是无法使用
而是用函数的参数及返回值就可以打破规则如下:
使用参数令函数可以使用全局变量
使用返回值令函数可以使用局部变量(注:php中函数的返回值只能返回一个结果,若想返回多个结果只能将返回值写成数组的结构,这样返回的结果是一个数组)
8、php类与对象
类好比是一个模板,其定义了相关的变量、方法等,而对象则是该模板的一个复制品一样,包含该模板的所有变量及方法等,不过调用变量或者方法是必须使用“ -> ”。
当想在类一个函数中去调用另外一个函数是可以使用 $this 来直接调用,在类的内部,专门调用自己的兄弟姐妹,如:
使用__construct()构造函数来接收对象传递给类的参数
9、php连接数据库
在php中使用mysqli($localhiot,$user,$pwd,$dbname)链接数据库,mysql_connect()好像已经落伍了。在该类中我们可以看connect_errno字段的值看起是否连接成功,若其为0则连接成功,connect_error为错误内容,连接成功其值为null
<!-- 连接数据库代码文件 --> <?php $host = '127.0.0.1'; $user = 'root'; $pwd = 'root'; $dbname = 'message_board'; $db = new mysqli($host,$user,$pwd,$dbname); $db->query("
软件打包发布 Release vs2017选用release生成.exe文件。
QT库打包 调用QT自动的windeployqt.exe文件打包qt相关的库。
流程:
选用qt对应版本的窗口。我用的是vs2017 64位的。注意别直接用cmd快捷键打开,在有多个qt版本或库的时候,比如装了anaconda。需注意选择正确的窗口。
cd 对应的exe文件夹,并运行,windeployqt.exe project.exe; 其中project.exe 为待打包的exe文件; 添加第三方库的DLL 比如halcon, 添加halcon.dll、 halconcpp.dll、hcanvas.dll等;即将项目中调用的非qt、vs2017的第三方库的dll拷贝到对应的exe所在的文件夹下。 Enigma Virtual Box 打包 第一个框选择待打包的exe;将刚刚生成的qt库和第三方库全部拖进第二个框中;点击process,会生成对应的打包exe文件。点击即可运行。
分享-前端业务场景的一些代码优化
前端开发基本每天都在写业务代码,有些场景我们可以用更好更优雅的方式去处理。今天给大家分享下我在实际业务场景下对代码的一些思考与优化,和大家探讨下。主要是两个方面:
如何利用js对象key唯一性简化代码逻辑如何利用异步和队列简化重复代码逻辑 如何利用js对象key简化代码 1. 利用对象来简化if else或者switch case
先简单举例说个业务场景:
运单可能有待发车、运输中、待收货、待回单、已收货…等状态,我们需要根据不同状态来显示不同的文案和图标颜色。如果我们采用vue的计算属性实现
第一种写法利用switch case或者if else:
switch (platformOrderStatus) { case 'transporing': return { name: '运输中', color: '#faad14' } case 'loaded': return { name: '已装货', color: '#faad14', } ... ... default: return { name: '未创建', color: '#ACBAC3', } } 第二种写法:
const maps = { 'transporing': { text: '运输中', color: '#faad14' }, 'loaded': { text: '已装货', color: '#faad14' }, 'arrived': { text: '已收货', color: '#72C650' }, .
C++基础功能:将文件路径进行分割,分别获取文件所在的文件夹名称、文件名称、以及文件扩展名
拓展:判断文件路径所在的文件夹是否存在,若不存在则创建文件夹
参考了简书上 1037号森林里一段干木头 的文章,在此附上链接并致谢!
Reference: https://www.jianshu.com/p/fadc2b4cba25
————————————————————————————————————————————
一. 分别获取文件所在的文件夹名称、文件名称、以及文件扩展名
代码:
#include <iostream> using namespace std; int main() { std::string path = "D:\\mydoc\\VS-proj\\SMTDetector\\x64\\Release\\0001.bmp"; int index = path.find_last_of("\\"); Get folderpath std::string folderPath = path.substr(0, index); //Get filename with extension std::string filename = path.substr(index+1, -1); //get extension of the file int index2 = path.find_last_of("."); std::string extendName = path.substr(index2 + 1, -1); std::cout << "path:\t" << path << std::endl; std::cout << "folderPath:\t" << folderPath << std::endl; std::cout << "
环境描述:
虚拟化平台:vmare5.5
物理机系统:esxi
虚拟机:centos7.5
交换机2台:锐捷和华为
机柜位置–》上面的交换机是华为的
26机柜1台物理机ip
10.1.1.1
机柜位置–》上面的交换机是锐捷的
12机柜 3台物理机IP
10.1.1.2
10.1.1.3
10.1.1.4
物理机插了2个网线,
a网线是物理机-管理网10.1.1.2
b网线是分配的是 vlan120 ,网段20.0.0.1/24
问题:
12机柜的3台物理机搭建的vlan120网段的虚拟机ping不通网关
第一步:我们初步怀疑是交换机的问题,让网络的同事检查一下交换机是否正常,网络的同事也查了配置说是正常的,在交换机上面直接插网线接笔记本,修改vlan120网段ping网关正常;给出反馈,交换机是正常的;
我自己又把12机柜的锐捷交换机的网线,插其他机柜的物理测试,配置vlan120网段ping网关正常
第二步:怀疑是vmare层面的虚拟交换机有问题,我自己看这个虚拟机换配置也看不出什么异常,后面让公司专门搞vmare平台的同事远程协助,测试调整,也未发现异常;
经过反复的折腾和讨论,最后觉得会不会是服务器的网卡坏了,然后打电话让服务器厂商免费更换网卡,死马当活马医。
第三步:让厂商换网卡,继续测试,还是不通;
第四步:厂商换网卡的中途,我回想起昨天晚上的思路;从26机柜上面的交换机接一根线,插12机柜上面测试一下vlan120,看是不是交换机的配置有问题;找了几根网线,加网线拼接器,终于把网线插好了,ping网关通了,好吧!!!最后终于知道是交换机的配置问题。
第五步:协调网络修改交换机配置,原来配置的是access 模式
12机柜物理机对应交换机后面的24,25,26口,换成了trunk模式,测试正常;
交换机VLAN 模式trunk和access 区别
access模式只能承载一个vlan的流量
trunk端口可以允许多个VLAN的数据包通过
华为
华为一面技术面: 简历上有实习经验的,会先问实习都做过哪些东西,哪些项目,画下图简单解释一下,在你做这个项目的时候,面临的最大的挑战是什么,如何解决的?
解释一下setup time和hold time是什么意思,如果不满足这两个时间,会发生什么。
现场写一个三分频电路代码。
华为二面技术面:一直问项目,问的很细,只有自己做过才能答上来,问到你解释不了为止。
选择验证的原因是什么,验证的工作设计工程师也可以做,为什么一定需要验证工程师呢?
考研分数以及你研究生的排名,最后现场写一个11011序列检测器,可以重复检测,用有限状态机是怎么写的,如果不用有限状态机又是如何实现的呢(移位寄存器)
华为三面主管面:在你的项目中,你是如何确保你的验证完备性的。详细讲述一个你所验证项目的功能点,以及你是如何验证这些功能点的,在哪里写的你的功能点代码。问了一下简历上所写的竞赛内容,都是几个人的小组,你在其中担任什么角色,你觉得为什么你能获得一等奖,重点在哪里。转专业的可能会问一些,为什么你要转专业,以及你是如何即完成学业又学习IC验证的。
英伟达
一面:一个IC设计面试官 一个IC验证面试官 时间一小时
外企一般上来都是英文的自我介绍
介绍简历中的项目 然后根据你所介绍的内容进行提问,问到了异步FIFO 单端口RAM 和 仲裁
跨时钟域的方法 这个问题其实很多公司都问过
低功耗的实现方法 自己做过工艺吗 工艺制备过程对功耗有何影响
fork join/fork join none/fork join any的区别
队列中插入数据的方法 为什么想来英伟达
二面:AMBA总线协议 APB/AHB/AXI的区别和联系
UART IIC SPI协议
项目中常用的debug方法有什么
无毛刺的时钟切换电路设计
建立时间保持时间违例怎么办
怎么看待英伟达收购ARM 还有哪些offer 等
兆易创新
笔试之后,北京这面当时是去的线下面试 时间大约40min
首先是自我介绍 然后介绍项目,给了纸和笔
然后在纸上画出项目的框架图,让你详细的讲述整个项目的流程,从如何搭建环境开始 问的很详细,然后根据你讲述的出问题
问到你项目过程中使用到了什么脚本语言 perl打开文件的指令是什么
然后针对项目问了一些使用到的总线,比如AHB总线,写出总线上的所有信号,并介绍,画出AHB总线的时序图等。
最后问了一下对MCU有什么认识,以及考研单科成绩和研究生的排名。
ZeKu科技
虽然ZeKu背景很大,但是十分缺人,知道的都是面了就上了,但是薪水会有不同的等级。
首先问了一下本科生和研究生学过的课程,如果与IC验证不是十份契合,他会问为什么你会选择验证这个岗位?以及你简历上的项目是自学的还是怎么学的?什么时候开始学的,学一个项目用了多久。
接下来都是十份常规的问题,IC设计的流程,从前端到后端全部完整的说一下;阻塞和非阻塞的区别;寄存器和锁存器的区别;动态数组、队列、定宽数组和关联数组的区别;待测设计和验证环境是如何关联的;对SV中约束都掌握哪些,如何在已有一个约束的前提下,对其它条件进行约束;项目中遇到的困难,你是如何解决的;到公司后,如何缩小与其它比你优秀同事之间的差距;最后就是你对我们公司还有什么想了解的。
JAVA支持的多线程开启方式 根据Oracle官方出具的Java文档说明,创建线程的方式只有两种:继承Thread或者实现Runnable接口。 但是这两种方法都存在一个缺陷,没有返回值,也就是说我们无法得知线程执行结果。虽然简单场景下已经满足,但是当我们需要返回值的时候怎么办呢? Java 1.5 以后的Callable和Future接口就解决了这个问题,我们可以通过向线程池提交一个Callable来获取一个包含返回值的Future对象,从此,我们的程序逻辑就不再是同步顺序。
下面是Java8实战书籍的原文:
Future接口在Java5中被引入,设计初衷是对将来某个时刻会产生的结果进行建模。它建模了一种异步运算,返回一个执行结果的引用,当运算结束后,这个引用被返回给调用方。在Future中触发那些潜在耗时的操作完成。 如下图: 我们从最初的串行操作变成了并行,在异步的同时,我们还可以做其他事情来节约程序运行时间。 图片来源:Java的Future机制详解 - 知乎
机智的小伙伴肯定会问了,什么,这篇不是讲JAVA8新特性,CompletableFuture的吗?怎么说起Future了? 不急,看下面
Future接口的局限性 当我们得到包含结果的Future时,我们可以使用get方法等待线程完成并获取返回值,注意我加粗的地方,Future的get() 方法会阻塞主线程。 Future文档原文如下
A {@code Future} represents the result of an asynchronous computation. Methods are provided to check if the computation is complete, to wait for its completion, and to retrieve the result of the computation. 谷歌翻译:
{@code Future}代表异步*计算的结果。提供了一些方法来检查计算是否完成,等待其完成并检索计算结果。 Future执行耗时任务 由此我们得知,Future获取得线程执行结果前,我们的主线程get()得到结果需要一直阻塞等待,即使我们使用isDone()方法轮询去查看线程执行状态,但是这样也非常浪费cpu资源。
图片来源:Java8实战
当Future的线程进行了一个非常耗时的操作,那我们的主线程也就阻塞了。 当我们在简单业务上,可以使用Future的另一个重载方法get(long,TimeUnit)来设置超时时间,避免我们的主线程被无穷尽地阻塞。 不过,有没有更好的解决方案呢?
我们需要更强大异步能力 不仅如此,当我们在碰到一下业务场景的时候,单纯使用Future接口或者FutureTask类并不能很好地完成以下我们所需的业务
将两个异步计算合并为一个,这两个异步计算之间相互独立,同时第二个又依赖于第一个的结果等待Future集合种的所有任务都完成。仅等待Future集合种最快结束的任务完成(有可能因为他们试图通过不同的方式计算同一个值),并返回它的结果。通过编程方式完成一个Future任务的执行(即以手工设定异步操作结果的方式)。应对Future的完成时间(即当Future的完成时间完成时会收到通知,并能使用Future的计算结果进行下一步的的操作,不只是简单地阻塞等待操作的结果) 正文 神奇的CompletableFuture 什么是CompletableFuture 在Java 8中, 新增加了一个包含50个方法左右的类: CompletableFuture,结合了Future的优点,提供了非常强大的Future的扩展功能,可以帮助我们简化异步编程的复杂性,提供了函数式编程的能力,可以通过回调的方式处理计算结果,并且提供了转换和组合CompletableFuture的方法。
交互式变基这个词是sourceTree的翻译。
交互式变基可以将多个提交合并为一个,当然他的功能不止于此。但一般用于以下情况:
在某个分支(比如dev)下做功能开发,当测试完毕,将要合并dev到master,但由于开发过程中有太多的提交,合并到master之后会让master的整个提交记录看起来不优雅,所以这时候可以用交互式变基去合并,这样做有两个好处:
rebase 可以让合并过程中不产生合并的那次提交,也就是说合并完成后master分支图谱仍旧是一根线。
squash多个提交保证开发分支的多次提交记录合并完成后仅有一个提交。
这两步是在一次交互式变基操作中一起完成的。
其实我们在dev上开发大部分情况都仅仅涉及到了一个功能点,比如某个bug fix,合并到master后理应仅有一个提交来保证master提交记录的可读性。
具体操作:
# 当前在dev分支
$ git rebase -i master
接着就会进入到一个交互式的界面,不要被吓到…
不要被这个界面唬到,这么多文字其实全是注释,他只是在告诉你怎么用。简单来说,我们仅仅用到squash,最上边的三行没有注释的是我的将要rebase 和 squash的三个提交。这个窗口完全和vim一样需要你去编辑。
在当前这个页面键入i(进入编辑模式),此时会出现光标
移动光标到第二行和第三行,将pick编辑为s
按esc,然后输入:(键盘上shift+:),输入wq,即保存退出。
上边pick编辑为s,就是意味着,将后两次提交“压缩”到第一次提交中。就是三次提交压缩为一次提交。
值得注意的是,第一行是不能改为s的,因为总需要个垫底的,否则你往谁身上压缩。
另外不要被编辑的复杂给唬到,其实vim就是一个linux的编辑器,一些大神甚至把他用作ide,你觉得复杂,只是因为你不熟练而已。
在保存退出后,立刻又进到另一个编辑界面。如下:
这个界面就干一件事:写提交信息。你上一步操作把提交合并了,但提交信息以哪次为准?这个你需要告诉git。
上图未注释的三行代码就是我三次提交的信息,注释掉你不需要提交信息。剩下的就是最终的提交信息。你可以都注释掉,自己重新写。总之,这个界面任何未注释的内容都将成为提交信息的一部分。
同样是vim的操作,保存退出即完成了全部的操作。
可以看到我基于master切出的dev2分支的三次提交被压缩成一次提交。
之后再次把dev2分支合并到master分支即可。可以看到提交图谱很干净:
1:下载mysql8镜像,选择对应的版本,我这里使用8.0.29
docker pull mysql/mysql-server:8.0.29 2:启动容器
docker run --name mysql8 -p 4306:3306 -e MYSQL_ROOT_PASSWORD=123456 -v D:\tools\dockerData\mysql8\data:/var/lib/mysql -v D:\tools\dockerData\mysql8\log:/var/log/mysql -d mysql/mysql-server:8.0.29 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --datadir=/var/lib/mysql --default-authentication-plugin=mysql_native_password 注意:
--default-authentication-plugin=mysql_native_password 这个参数是修改密码策略,原来Mysql在之前的版本的关于password的加密方法都是使用的 mysql_native_password,不过到MySQL8.0的时候换成了caching_sha2_password 3:通过命令 docker ps 查看容器是否启动成功,这个时候使用Navicat连接mysql会报错,提示不允许访问,这个时候进入容器内部修改权限。
1:docker exec -it mysql8 bash 2:mysql -uroot -p123456 3:use mysql; 4:select user,host from user; 5:update user set host='%' where user='root'; 6:flush privileges; 4:重新使用Navicat连接mysql即可
问题描述: 下载pytorch时一直出现
CondaHTTPError: HTTP 000 CONNECTION FAILED for url 于是将torch安装包下载下来,想要安装,出现错误
PackagesNotFoundError: The following packages are not available from current channels: 解决办法: 往下看,发现给出了解决办法
进入网站:
https://anaconda.org/
注册账号后进行搜索:
比如这里我搜索的是torchvision
根据自己的需求选择相应版本的包
运行以下命令即可
如果这个方法还是不能下载
选择不使用conda命令,使用file,如下图所示:
根据
根据自己的系统和python版本,cuda版本,下载所需要的.bz2文件,将文件放入./anaconda3/pkgs/文件夹下,然后运行以下代码
conda install --use-local torchvision-0.6.0-py37_cu92.tar.bz2 .bz2文件名是自己所下载的文件名
spring声明式事务管理默认对非检查型异常和运行时异常进行事务回滚,而对检查型异常则不进行回滚操作。
1、异常 1.1、检查型异常 检查型异常(编译器要求必须处置的异常):正确的程序在运行中,很容易出现的、情理可容的异常状况。可查异常虽然是异常状况,但在一定程度上它的发生是可以预计的,而且一旦发生这种异常状况,就必须采取某种方式进行处理。
除了RuntimeException(运行时异常)及其子类以外,其他的Exception类及其子类都属于检查型异常。这种异常的特点是Java编译器会检查它,也就是说,当程序中可能出现这类异常,要么用try-catch语句捕获它,要么用throws子句声明抛出它,否则编译不会通过,编译器一般会给出错误提示。
例如:一个读取文件的方法代码逻辑没有错误,但程序运行时可能会因为文件找不到而抛出FileNotFoundException,如果不处理这些异常,程序将来肯定会出错。所以编译器会提示你要去捕获并处理这种可能发生的异常,不处理就不能通过编译。
1.2、非检查型异常 非检查型异常(Unchecked)是指编译器不会检查这类异常,不检查的则开发者在代码的编辑编译阶段就不是必须处理,这类异常一般可以避免,因此无需处理(try …catch)。如果不处理这类异常,集成开发环境中的编译器也不会给出错误提示。非检查型异常包括:运行时异常(RuntimeException与其子类)和错误(Error)。
例如:你的程序逻辑本身有问题,比如数组越界、访问null对象,这种错误你自己是可以避免的。编译器不会强制你检查这种异常。
1.3、运行时异常 运行时异常都是RuntimeException类及其子类异常,如NullPointerException、IndexOutOfBoundsException等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。
当出现RuntimeException的时候,我们可以不处理。当出现这样的异常时,总是由虚拟机接管。比如:我们从来没有人去处理过NullPointerException异常,它就是运行时异常,并且这种异常还是最常见的异常之一。
1.4、非运行时异常 非运行时异常是RuntimeException以外的异常,类型上都属于Exception类及其子类。如IOException、SQLException等以及用户自定义的Exception异常。对于这种异常,JAVA编译器强制要求我们必需对出现的这些异常进行catch并处理,否则程序就不能编译通过。所以,面对这种异常不管我们是否愿意,只能自己去写一大堆catch块去处理可能的异常。
参考地址:异常机制
2、声明式事务 在service层方法上添加Transactional注解,指定回滚异常类型
//当出现Exception时,进行事务回滚 @Transactional(rollbackFor = Exception.class) //当出现RunTimeException时,不进行事务回滚 @Transactional(notRollbackFor=RunTimeException.class) 提示:
1、springboot项目并不需要@EnableTransactionManagement注解开启事务
2、一般try catch都在controller层处理,service层进行回滚加上注解@Transactional(rollbackFor=Exception.class)即可,如果service正常执行,在controller层报错,则不会回滚
一、题目 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4
二、代码 class Solution { public int search(int[] nums, int target) { int l = 0; int r = nums.length - 1; while(l <= r){ int m = (l + r) / 2; if(target == nums[m]) return m; else if(target > nums[m]) l = m + 1; else r = m - 1; } return -1; } }
如题,博主在实习阶段遇到了这个棘手的问题,因为wsl本质上也是remote的一种,而ssh也是remote,如何在wsl的基础上再ssh远程连接服务器?博主在找遍百度的各种方法后无果,然后抱着试一试的心态在谷歌上搜索,最终找到解决此问题的方法:
①新建一个ssh.bat文件,可以放在任意位置
②内容编辑为:
C:\Windows\system32\wsl.exe ssh %* Tips:这里bat中%*的作用是命令行参数的占位符,因为连接远程服务器是ssh
xxx,这里变成C:\Windows\system32\wsl.exe ssh xxx,巧妙的解决了博主遇到的问题
③打开vscode,在extension中找到"remote-ssh",然后右击,选择"extension setting",下滑找到 “remote.SSH.path”,一开始默认为空,在这里填入新建的ssh.bat文件路径。
reference:
https://stackoverflow.com/questions/60150466/can-i-ssh-from-wsl-in-visual-studio-code
目录 卡特兰数定义递推公式公式1:公式2:公式3:公式4: 应用场景公式1证明公式2证明公式3证明公式4证明 例题 卡特兰数 定义 在oeis上可以看到卡特兰数的定义如下。
递推公式 f[0] = f[1] = 1
公式1: f[n]=f[0]f[n-1]+f[1]f[n-2]+...+f[n-1]f[0]'
公式2: f[n]=f[n−1]∗(4∗n−2)/(n+1)
公式3: f[n]=C[2n,n]/(n+1)(n=0,1,2,...),C是组合数
公式4: f[n]=C[2n,n]−C[2n,n−1],C是组合数
应用场景 一共有n对括号'(' ')',求出所有的排列的个数f(n)。(在前i个符号中,左括号数量一定比右括号多)。
显然有f(0)=1; f(1)=1。
借助于这个问题:引入公式的证明
公式1证明 证明:在n对括号的排列中,假设最后一个括号和第i个左括号匹配。则在第i个左括号之前,一定已经匹配上了(i-1)对左括号。如下图,因此,此种情况的数量为f(i-1)*f(n-i)。(1<=i<=n)最后一个右括号可以1~n个左括号匹配共n种情况。
因此,对i从1到n的情况求和得到∑f(i-1)f(n-i),即可得到递推公式1。
公式2证明 通过公式4很容易变换得到,给出公式4的证明。
公式3证明 通过公式4很容易变换得到,给出公式4的证明。
公式4证明 证明:对于给定的n对括号,如果不考虑任意一个前缀序列中的'('不能比'')少这一个条件,则一共有C[2n][n]种结果(2n个位置插入n个右括号)。现在只要删除所有结果中不符合条件的部分即可。
令 g(x) :前缀x中的左括号数减右边括号数的差。如果不符合条件,一定是在排列中出现了某一点的g(x)<0。
找到第一次出现g(x)=-1的位置,将之后的所有g(x)取反。最终g(n)变为g(n) = -2。
对于任何一种非法情况,做上述变换之后一定会使得g(n) = -2,等价于在最终结果时右括号比左括号多2个。因此非法情况数位C[2n][n+1]
即f[n]=C[2n,n]−C[2n,n−1]=C[2n,n]−C[2n,n+1]。
参考https://www.cnblogs.com/zyt1253679098/p/9190217.html
例题 P1044 栈
hdu1134 Game of Connections(此题用到高精度大数)
一、介绍 该项目以虚拟现实技术课程中老师所教授 UnityChan 相关 人物角色动画控制为基础,引入室外场景模型并添加光照和阴影;添加交互性元素如 发射炮弹,键盘按钮移动坦克;实现第一、三人称视角切换。
开发平台为 Unity 2018.4.21f1(64-bit),操作系统为 Windows 10(64 位)。
二、操作说明 使用 Visual Studio 编译这个游戏,然后运行。
2.1 这个是游戏刚开始进入时的场景 2.2 移动人物漫游场景 WSAD 键用来控制坦克的位置,行走用户以第三人称视角在整个场景中进行移动。
2.3 移动鼠标切换视角 可以移动鼠标,来切换视角
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CHzGIqX2-1653294122999)
(https://www.writebug.com/myres/static/uploads/2022/5/21/44912dd0f2bce5f0058dcf67ebe48014.writebug)]
2.4 鼠标点击发射炮弹 点击鼠标的时候,可以发射炮弹到一个位置,观看到炸弹爆炸的效果
三、探索的技术 3.1 多摄像机切换 using UnityEngine; public class CameraControl : MonoBehaviour { public float m_DampTime = 0.2f; public float m_ScreenEdgeBuffer = 4f; public float m_MinSize = 6.5f; [HideInInspector] public Transform[] m_Targets; private Camera m_Camera; private float m_ZoomSpeed; private Vector3 m_MoveVelocity; private Vector3 m_DesiredPosition; private void Awake() { m_Camera = GetComponentInChildren<Camera>(); } private void FixedUpdate() { Move(); Zoom(); } private void Move() { FindAveragePosition(); transform.
文章目录 构造安全KNN加密函数的要求——非距离可恢复一个简单的KNN构造能抵抗选择密文攻击的KNN构造Random Asymmetric Splitting将d维向量扩展为d'维 构造安全KNN加密函数的要求——非距离可恢复 满足以下条件,就不是距离可恢复加密了,便可以用于构造安全KNN
上面的定义就要求,E(q)!=E(p),即使q==p
最简单的构造是这样的:
p和q的标量积可以表示为pTIq=(pTM)(M-1q),那么我们让p’=ET(p,K)=MTp,同时q’=EQ(q,K)=M-1q
那么满足要求(i)p’Tq’=pTMM-1q = pTq
同时满足要求(ii)p1’Tp2’=p1TMMTp2 != pTq
一个简单的KNN构造 比较方法:
这两个(d+1)维点的标量积可以表示为
但是这种方案不能对抗选择密文攻击
证明如下:
能抵抗选择密文攻击的KNN构造 Random Asymmetric Splitting 将查询向量q或者数据点p一分为二,假如
将d维向量扩展为d’维 将d维向量扩展为d’维,(d<d’)并保证增加的维度的乘积为零
目录 一、电磁场中的一维结构二、传递矩阵法1、模型结构2、4×4矩阵方法(需要sort)(1)前提内容(2)4×4矩阵方程式(用于求解电磁场方程)(3)LHI 情况下的解(4)计算传输矩阵T(5)稳定性问题 本文资料来源(配图):EMPossible_CEM
1、课件资料:https://empossible.net/academics/emp5337/
2、视频资料:
youtube:https://www.youtube.com/watch?v=JOgtCeUMIAc
bilibili:https://www.bilibili.com/video/BV1ck4y1m73u?p=2
一、电磁场中的一维结构 将三维结构降为一维结构:
二、传递矩阵法 1、模型结构 模型结构的建立是基于上一节的内容,也就是通过将三维结构降为一维结构来进行分析的,类似于切片的方法。如下图所示,假设有一束光打在由四层介质板构成的器件上。
将Layer1最靠前一侧的界面0(z=0处)的电磁场定义为E0和H0,将Layer1靠后一侧的界面1的电磁场定义为E1和H1。当发射电磁波时,对于这个器件而言,我们假设电磁波是从界面0出发,经过Layer1后,到达界面1的,因此若要建立起两个界面电磁场之间的关系,关键就在于对Layer1层的分析。
而传输矩阵(Transfer Matrix,通常称为T矩阵),就是我们用来构建起两个界面电磁场之间关系的一个矩阵,即E0和H0经过T矩阵的变换后变为了E1和H1,也由此我们可以认为:事实上,T矩阵是表征了Layer1自身的一些属性(如:电导率、磁导率等)对电磁波产生的影响。
基于此,我们可以用一个简单的公式来表示两个界面电磁场间的关系,即:[E1, H1]=T1 • [E0, H0],T为矩阵;同样地,对于界面2的电场E2和界面1的电场E1,我们也可以获得关系式:[E2, H2]=T2 • [E1, H1]=T2 • T1 • [E0, H0],即如上图所示。
按照以上的方法,对整个器件涉及到的界面关系均进行推导,我们即可以获得输入界面和输出界面之间的电磁场关系,如下图所示。对于该关系中所有涉及到的T矩阵的累乘,我们将之称为全局传输矩阵(Global Transfer Matrix)。
此时问题的关键,就变为了要如何推导出T矩阵? 这里,我们先给出结果(下图),再对过程进行分析。由下图可以看出,有两种方法可以获取最终的解,一种方法是需要 sort(分类)的,在这个方法过程中需要使用到4×4矩阵;另一个方法是不需要 sort 的,其使用到的是2×2矩阵。
2、4×4矩阵方法(需要sort) (1)前提内容 在均匀介质中,假设电磁波的入射方向是 +z 方向,则:
同理,在均匀介质中,假设电磁波的入射方向是 k ⃗ \vec{k} k 方向,则:
对于器件模型而言,z轴通常表示了多层的结构,x,y方向则表示的是面。通常来说,对于z轴某一点所在面,其沿x和y方向延伸出去的部分都是均匀的,而沿z轴方向延伸出去的部分则是非均匀的(因为层与层的性质不同)。因此,我们可以对x和y方向的电场进行求导,如下图所示:
但由于沿z方向结构的非均匀性,故而其不能直接进行求导:
(2)4×4矩阵方程式(用于求解电磁场方程) 在 Lecture 1 学习笔记 (1) 中,通过对麦克斯韦方程组的变形和展开,得到了一组关于 E 和 H 在三个方向的等式,它们是通常用于计算电磁学中的麦克斯韦方程组,我们将之称为Starting Point for CEM,即:
需要注意的是:这些等式对应的是LHI的情况( [ ε \varepsilon ε]= ε \varepsilon ε,[ μ \mu μ]= μ \mu μ )
目录
一、合并两个有序链表
1、题目要求
2、基本思路
3、代码实现 二、*链表分割 1、题目要求
2、基本思路
3、代码实现
三、删除链表中重复的结点
1、题目要求
2、基本思路
3、代码实现
一、合并两个有序链表 1、题目要求 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
21. 合并两个有序链表 - 力扣(LeetCode) 2、基本思路 这个题目给出了两个升序的链表,需要我们合并为一个升序的链表,首先我们可以想到可以建立一个新的结点newHead这个结点来当做新的链表的头结点,然后我们在新建立一个结点temp来记录新的链表头结点后面的结点,然后依次比较两个有序链表中各个结点的大小,依次排序加入到新的链表后面,这边利用了链表的尾插法,最后判断首先遍历完了那个链表,说明另外一个链表还没遍历完,因为每个链表都为升序链表,因此直接把得到的尾结点与没有遍历完的链表部分连接即可。
3、代码实现 class Solution { public ListNode mergeTwoLists(ListNode list1, ListNode list2) { if(list1 == null && list2 == null){ return null; } ListNode newHead = new ListNode(); ListNode temp = newHead; while(list1 != null&&list2 != null){ if(list1.val < list2.val){ temp.next = list1; list1 = list1.next; temp = temp.
那一天
“灵魂调参师”们再次回忆起了
被数据集支配的恐惧
……
图源:网络
数据是决定模型质量的关键,好的模型离不开好的数据集。 然而,数据准备环节占了我们太多的时间,数据集稀缺、查找过程繁琐、无法预览、难下载、数据集信息不全、数据格式不统一、质量参差不齐等问题严重影响了模型训练的效率与体验。 OpenDataLab 来啦 如何提高数据准备效率,解决“找数据、下数据、用数据”的麻烦?
深度研究AI 人的需求后,我们重磅推出了OpenDataLab 公开数据集平台,集海量优质的多模态数据集资源、数据集智能检索、数据可视化展示、数据在线预览、下载优化、标准化管理等功能于一体,力争将平台打造成企业、高校、科研机构等的AI 模型训练的必备利器,帮大家解决数据集烦恼。
五大品质服务 01 海量多模态数据集一键查询 痛点回顾
过去大家为了找到目标数据集,逛遍国内外各种网站,会发现高质量数据集资源难求,许多平台提供的数据集种类过于单一。
OpenDataLab解决方案
收录了海量最新、热门、经典的数据集,涵盖30+应用场景、20+的标注类型;平台提供了极简的数据集搜索路径,只需2步:打开网址,输入关键字,即可查询;支持中英双语版本切换,全程无广告,无需登录、无需VPN,极佳的使用体验。 图源:OpenDataLab 搜索界面
02 免费高速下载 痛点回顾
很多数据集体量大,动辄十几个G,有的甚至还需要科学上网才能下载,下载速度慢得让人崩溃,网速中断后又得重新开始;同时市面上很多数据集网站有下载次数、容量等限制。
OpenDataLab解决方案
数据集存储在国内服务器,一键云端下载,无需担心操作复杂、费时;登录后即可放心免费下载,无下载次数、容量等限制,无付费、积分等要求;数据集可拆成多个压缩包,自主选择下载,减小一次性下载的压力;支持断点续传,任务中断也无需担心。 图源:OpenDataLab 数据集下载界面
03 智能检索 痛点回顾
国内外数据集均比较分散,统一检索的入口少;大部分仅支持数据集名称检索、标注类型筛选。
OpenDataLab解决方案
支持模糊搜索、关键词联想搜索、分词搜索,扩大检索命中率;支持多维度筛选数据集:数据类型、标注类型、任务类型,按需筛选查看。 图源:OpenDataLab 智能检索示意
04 标准化处理与可视化展示 痛点回顾
不同机构发布的数据集信息不统一,标签、格式多样;很多无法提前预览,通常要下载后才能检查、判断数据是否符合需要。
OpenDataLab解决方案
对数据集信息进行标准化处理,数据集核心基本信息一览无余;全面又整洁的元数据信息,不再费力到处搜罗关联论文、标注结果等信息;提供图像、视频、音频数据集在线预览,不再费力解读是否可用。 图源:OpenDataLab 数据集在线预览界面
05 数据安全保障 痛点回顾
找到数据集,还需要找License、发布机构许可等,确认数据使用范围,降低使用风险。
OpenDataLab解决方案
平台统一对数据集License梳理,并结构化展示,帮助用户判定许可,限制,条件等范围;严格的数据集质量评测流程、合规准入审核,不用担心一不小心使用数据集侵权;数据集发布机构、发布链接展示,支持自主溯源、验证。 图源:OpenDataLab 数据集许可证、发布机构等信息界面
立即体验 遇到OpenDataLab 这么便捷、好用的AI 数据开放平台,还在等什么?
立即注册,即享品质服务:OpenDataLab
内核调整 cat > /etc/sysctl.d/k8s.conf <<EOF net.bridge.bridge-nf-call-iptables=1 net.bridge.bridge-nf-call-ip6tables=1 net.bridge.bridge-nf-call-arptables = 1 net.ipv4.ip_forward=1 net.ipv4.tcp_tw_recycle=0 net.core.somaxconn = 32768 vm.swappiness=0 # 禁止使用 swap 空间,只有当系统 OOM 时才允许使用它 vm.overcommit_memory=1 # 不检查物理内存是否够用 vm.panic_on_oom=0 # 开启 OOM fs.inotify.max_user_instances=8192 fs.inotify.max_user_watches=1048576 fs.file-max=52706963 fs.nr_open=52706963 net.ipv6.conf.all.disable_ipv6=1 net.netfilter.nf_conntrack_max=2310720 net.ipv4.conf.all.rp_filter = 1 net.ipv4.neigh.default.gc_thresh1 = 80000 net.ipv4.neigh.default.gc_thresh2 = 90000 net.ipv4.neigh.default.gc_thresh3 = 100000 EOF kube-proxy开启ipvs的前置条件 modprobe br_netfilter cat > /etc/sysconfig/modules/ipvs.modules <<EOF #!/bin/bash modprobe -- ip_vs modprobe -- ip_vs_rr modprobe -- ip_vs_wrr modprobe -- ip_vs_sh modprobe -- nf_conntrack modprobe br_netfilter EOF cat<<END> install-1.
一、查询语句: //查询语句一 select count(u.id) from user u LEFT JOIN dept d on u.dept_id=d.id LEFT JOIN user_role ur on u.account=ur.account LEFT JOIN role r on ur.role_id= r.id where u.has_del=0 GROUP BY u.account order by u.create_time desc //查询语句二 select u.id, u.account,u.username,u.mobile,u.idcard,u.user_status,u.org_id,u.dept_id,u.create_time,ur.role_id,r.role_name,d.dept_name from user u LEFT JOIN dept d on u.dept_id=d.id LEFT JOIN user_role ur on u.account=ur.account LEFT JOIN role r on ur.role_id= r.id where u.has_del=0 GROUP BY u.account order by u.create_time desc limit 0,10 二、完整报错信息: 1055 - Expression #1 of ORDER BY clause is not in GROUP BY clause and contains nonaggregated column 'identity-qrcode-yqfk.
什么是循环依赖? 抛出的异常是:beanCurrentlyInCreationException
标题 单例bean中,属性互相引用的场景;
两中注入方式对循环依赖的影响? 构造方法注入,可能会造成循环依赖的问题;建议用setter方法注入;
即AB循环依赖问题只要A的注入方式是setter且singleton,就不会有循环依赖问题;
注意:默认的单例(singleton)场景是支持循环依赖的,不报错;
原型(prototype)场景是不支持循环依赖的,会报错;
重要结论: DefaultSingletonBeanRegistry
标题 标题 一级缓存:也叫单例池;存放已经经历了完整生命周期的bean对象(即已经初始化好了的bean);
二级缓存:存放早期暴露出来的Bean对象,Bean的生命周期未结束(属性还没填充完);(即实例化了,但未初始化的bean)
三级缓存:存放可以生成bean的工厂;(存放的是FactoryBean。假如A类实现了FactoryBean,那么依赖注入的时候不是A类,而是A类产生的bean)
只有单例的Bean会通过三级缓存提前暴露来解决循环依赖问题,而非单例的bean,每次从容器中获取都是一个新的对象,都会重新创建,所以非单例的Bean是没有缓存的,不会将其放到三级缓存中。
标题 标题 文字总结 调用的流程图:
概述: ***(简单说一下,不重点讲述啦)
GPRS 隧道协议 (GTP) 是一种隧道协议,用于 GPRS、UMTS、LTE 和 5G 网络。它分为两个独立的协议:GTP-C 和 GTP-U。GTP-C用于GPRS核心网络中,用于不同网络节点之间的信令。GTP-U 用于承载用户数据。
GTP 消息头 GTP-C和GTP-U协议使用的GTP头是变长度的。GTP头的最小长度是8个字节。有三个标志用来指示三个可选字段是否使用:PN标志,S标志和E标志。PN标志用于指示是否使用N-PDU可选字段;S标志用于指示是否使用GTP序号;E标志用于指示是否使用扩展头可选字段,使用这个标志可以使将来对本规范进行扩展时不需使用另外的版本号。假如设置了三个标志中的任一个,GTP头的长度至少是12个字节,且接收者应处理相应的字段。发送者应把所有未使用的位置零,接收者不处理未用字段。
GTP-C和GTP-U对GTP头某些字段的使用是不同的。
必选字段: - 版本号(Version):3bit,这个字段用于确定GTP协议的版本。
- 协议类型(PT):这个位用于区分GTP(PT置为’1’)和GTP’(PT置为’0’)协议。
扩展头标志(E):这个标志置’1’表示有下一个扩展头字段。置’0’表示没有下一个扩展头字段,或有但不必解释。
序号标志(S):这个标志置’1’表示有序号字段。置’0’表示要么没有序号字段,要么有但不必做出解释。在GTP-C消息中S标志应置’1’。
N-PDU编号标志(PN):这个标志置’1’表示有N-PDU编号字段。置’0’表示要么没有N-PDU编号字段,要么有但不必做出解释。这个标志仅对GTP-U有意义。正因为如此,GTP-C不使用这个标志,GTP-C的接收实体应忽略此标志。
消息类型:这个字段指出GTP消息的类型。有效的GTP-C和GTP-U消息类型值后续再讲。
长度:这个字段指出以字节为单位的净荷长度,即分组中除了GTP头的必选部分外剩余部分的长度(即除去前面的8个字节)。序号、N-PDU编号或任何扩展头应作为净荷部分考虑,即包含在长度计数中。
隧道端点标识符(TEID):这个字段清楚地标识了对端的GTP-U或GTP-C协议实体中的隧道端点。由GTP隧道的对端本地分配TEID值,供GTP隧道的发起方使用。通过GTP-C(在Iu接口上使用RANAP消息)消息在隧道的两个端点间交换TEID值。
Sequence number::2字节,对T-PDU进行编码,可用于用户面排序,重传等目的
可选字段:
序号:这个字段在GTP-U中是可选的。对GTP-C控制面消息,序号用于事务标识。通过GTP-U隧道传输时,如果必须保护传输顺序,用次字段对T-PDU进行编号,且每传输一个T-PDU就增加序号值。
N-PDU标号:这个字段在SGSN间的路由区更新过程中和某些系统间切换过程(如2G和3G无线接入网间切换)中使用。当MS和SGSN间的通讯工作在确认模式下时,使用这个字段协调它们间的数据传输。这个字段的确切意义取决于使用场合。如GSM/GPRS到GSM/GRPS,这个字段就是SNDCP N-PDU编号。
下一个扩展头类型:这个字段定义在G-PDU中紧接着这个字段的扩展头的类型。
Octets 8 7 6 5 4 3 2 1 1 版本号 协议类型 (*) E S PN 2 消息类型 3 长度(1st Octet) 4 长度 (2nd Octet) 5 隧道端点标识符TEID(1st Octet) 6 隧道端点标识符TEID(2nd Octet) 7 隧道端点标识符TEID(3rd Octet) 8 隧道端点标识符TEID(4th Octet) 9 序号(1st Octet)1) 4) 10 序号(2nd Octet)1) 4) 11 N-PDU编号2) 4) 12 下一个扩展头类型3) 4) (*) 这个位是空位应置零,接收者不解释。
100个Python练手小程序,学习python的很好的资料,覆盖了python中的每一部分,可以边学习边练习,更容易掌握python。
【程序1】
题目:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?
1.程序分析:可填在百位、十位、个位的数字都是1、2、3、4。组成所有的排列后再去
掉不满足条件的排列。
2.程序源代码:
for i in range(1,5): for j in range(1,5): for k in range(1,5): if( i != k ) and (i != j) and (j != k): print (i,j,k) 【程序2】
题目:企业发放的奖金根据利润提成。利润(I)低于或等于10万元时,奖金可提10%;利润高
于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可可提
成7.5%;20万到40万之间时,高于20万元的部分,可提成5%;40万到60万之间时高于
40万元的部分,可提成3%;60万到100万之间时,高于60万元的部分,可提成1.5%,高于
100万元时,超过100万元的部分按1%提成,从键盘输入当月利润I,求应发放奖金总数?
1.程序分析:请利用数轴来分界,定位。注意定义时需把奖金定义成长整型。 2.程序源代码:
bonus1 = 100000 * 0.1 bonus2 = bonus1 + 100000 * 0.500075 bonus4 = bonus2 + 200000 * 0.5 bonus6 = bonus4 + 200000 * 0.3 bonus10 = bonus6 + 400000 * 0.
页面效果如图:
页面代码实现如下:
(记得要安装对应依赖 [screenfull],store里面要添加对应配置)
<div class="userInfo text-left"> <el-dropdown :show-timeout="0"> <div> {{ $store.state.user.fullName }},欢迎您 <i class="el-icon-arrow-down el-icon--right" /> <el-dropdown-menu slot="dropdown"> <el-dropdown-item @click.native="logout"> <i class="iconfont ico-zhuxiao" /> 注销 </el-dropdown-item> <el-dropdown-item @click.native="$router.push('/change-pass')"> <i class="iconfont ico-mima" /> 修改密码 </el-dropdown-item> <el-dropdown-item @click.native="handleScreenFull"> <i :class="['iconfont', isFullscreen ? 'ico-tuichuquanping' : 'ico-quanping']"></i> {{ isFullscreen ? '退出全屏' : '进入全屏' }} </el-dropdown-item> </el-dropdown-menu> </div> </el-dropdown> <div class="nowTime">{{ nowTime }}</div> </div> import screenfull from 'screenfull' export default { computed: { .
树与二叉树 # -*- coding: utf-8 -*- from collections import deque class Queue(object): # 借助内置的 deque 我们可以迅速实现一个 Queue def __init__(self): self._items = deque() def append(self, value): return self._items.append(value) def pop(self): return self._items.popleft() def empty(self): return len(self._items) == 0 class Stack(object): def __init__(self): self._items = deque() def push(self, value): return self._items.append(value) def pop(self): return self._items.pop() def empty(self): return len(self._items) == 0 class BinTreeNode(object): def __init__(self, data, left=None, right=None): self.data, self.left, self.right = data, left, right class BinTree(object): def __init__(self, root=None): self.
转载1(8种模式)
转载2(应用场合)
在学到后面的知识时经常惯性的直接使用gpio的复用输出模式而没有考虑其他情况 在此学习补充
题目描述 :
给定一颗树,书中包含 n 个结点(编号 1∼n )和 n−1 条无向边。
请你找到树的重心,并输出将重心删除后,剩余各个连通块中点数的最大值。
重心定义:重心是指树中的一个结点,如果将这个点删除后,剩余各个连通块中点数的最大值最小,那么这个节点被称为树的重心。
输入输出格式 :
输入
第一行包含整数 n,表示树的结点数。
接下来 n−1 行,每行包含两个整数 a 和 b,表示点 a 和点 b 之间存在一条边。
输出
输出一个整数 m,表示将重心删除后,剩余各个连通块中点数的最大值。
输入输出样例 :
输入
9 1 2 1 7 1 4 2 8 2 5 4 3 3 9 4 6 输出
4 #include<bits/stdc++.h> using namespace std; using ll = long long; int dir[4][2] = { 1, 0, -1, 0, 0, 1, 0, -1 }; //using lll = __int128;template <class T> istream& read(T& x, istream& cin = std::cin){T num = 0;bool f = 0;char ch = 0;while (!
题意描述:
给定一棵树,树中包含 n 个结点(编号1~n)和 n−1 条无向边,每条边都有一个权值。
现在请你找到树中的一条最长路径。
换句话说,要找到一条路径,使得使得路径两端的点的距离最远。
注意:路径中可以只包含一个点。
输入格式
第一行包含整数 n。
接下来 n−1 行,每行包含三个整数 ai,bi,ci,表示点 ai 和 bi 之间存在一条权值为 ci 的边。
输出格式
输出一个整数,表示树的最长路径的长度。
数据范围
1≤n≤10000,
1≤ai,bi≤n,
−1e5≤ci≤1e5
输入样例:
6 5 1 6 1 4 5 6 3 9 2 6 8 6 1 7 输出样例:
22 输入样例:
6 3 1 1000 1 4 10 4 2 100 4 5 50 4 6 100 输出样例:
1110 对于树上的每一个节点都求出它所有子树的最大深度和第二大深度,两者相加便是以该节点为根节点的子树的最大链长
vector 邻接表
文章目录 前言一、事情起因二、分析stack日志 1.列出当前进程的运行列表 2.打印进程的GC情况3.列出进程下消耗最高的线程4.导出进程的快照5.查看线程异常信息6.导出进程的dump文件 三、dump文件分析 1.MAT工具分析报告 2.Histogram大对象分析3.优化后结果 总结 前言 最近遇到了一次生产环境上服务CPU高的问题,本篇会记录问题处理全过程,并分享给大家,希望能够帮助到遇到同样问题的人。
一、事情起因 运营在群里面反馈系统(3年前老项目)速度很慢,然后自己也去试了一下发现所有页面都数据加载都很慢,然后服务器也报警了,这个服务CPU彪升到100%了,初步推测是内存泄漏了。
二、分析stack日志 1.列出当前进程的运行列表 指令: top -c
如上图 PID=21398的进程CPU已经超过100%
2.打印进程的GC情况 指令:jstat -gcutil 21398 1000 1000
幸存者空间异常?
S0 0.00 S1 100.00 ?幸存者区的空间是不是很奇怪,我第一时间也没有看懂。
仔细看了一下,JVM参数指定的是G1GC,因为G1的堆布局跟HotSpot VM里其它GC不一样——它只有一组逻辑上的survivor space,而不像其它HotSpot GC一样有两段明确、固定的地址空间用作survivor space——所以用jstat看G1的话肯定是survivor space 0显示0%,survivor space 1显示100%,这个是正常的。
老年代空间占用率超过 82%,老年代空间占用率高一般都是代码写的有问题,这个和之前猜测的内存泄漏问题可以对上(加上重启服务止血后所有功能都正常了,锁定是内存泄漏问题)。
方法区空间占用率超过94.66,方法区存储的是类的加载信息、常量、静态变量等,按照经验来说方法区内存溢出都是新导入的框架不兼容等问题导致的,排查了一下没有引入奇怪的框架,之后分析重点放在 常量和静态变量这块。
3.列出进程下消耗最高的线程 指令 :top -Hp 21398
如上图 PID=21771的线程CPU已经 99.9%
21771是十进制的数,快照中线程是十六进制,将其转为十六进制:550b
4.导出进程的快照 指令: jstack -l 21398 > ./21398.stack
备注: stack文件很小
5.查看线程异常信息 指令:jstack -l 21398 > ./21398.stack
从stack日志中也只能看出来好多线程都在等待中且有死锁问题,如果有经验的就能从大量线程time_waiting就能猜到是tcp连接池有问题,在项目中全局搜索了一下发现根本就没有配置线程池,那么具体是什么问题还得分析dump文件。
第一步:打开 访达文件夹
第二步: command + shift + g 搜索,输入 /private/etc/hosts 找到 hosts 文件
第三步:编辑修改(修改之前需要备份),输入
http://github.com 204.232.175.94 http://gist.github.com 107.21.116.220 http://help.github.com 207.97.227.252 http://nodeload.github.com 199.27.76.130 http://raw.github.com 107.22.3.110 http://status.github.com 204.232.175.78 http://training.github.com 207.97.227.243 http://www.github.com 注意:hosts 文件是不能直接修改的,需要使用备份替换。一般情况下,修改原有的 hosts 文件时,系统会自动提醒你保存备份,修改完成,使用备份替换原有文件即可。
第四部:测试
打开网站看看是否可以正常访问。https://github.com/
CNAS认证什么意思?华奖技术提供一站式实验室CMA、CNAS认证认可咨询服务,保证您的实验室顺利拿到CMA、CNAS认证资质,不过退款;
中国合格评定国家认可委员会(英文名称:China National Accreditation Service for Conformity Assessment,英文缩写:CNAS)是由国家认监委根据《中华人民共和国认证与安全管理条例》授权设立的。认可”。国家认可机构负责认证机构、实验室、检验机构等相关机构的认可工作。
CNAS由原中国国家认可委员会(CNAB)和原中国实验室国家认可委员会(CNAL)合并而成。 CNAS通过对合格评定机构(如认证机构、实验室、检验机构)的管理和活动进行评价和监督,确认其是否具备开展相应合格评定活动(如认证、检测校准、检验等)的能力.)、确认其符合性评价活动的权威性,起到认可和约束的作用。
CNAS认证流程:
第1步:前期规划:实验室建设、仪器采购校准、人员招聘与培训、质量手册、程序文件的编制及审核定稿、实验室质量体系诊断及检测水平评估等。
第2步:建立体系:按照CNAS相关领域要求、认可准则要求等,建立起符合自己实验室现状的管理体系,并有效运行。
第3步:网上申请:登录CNAS网站:www.cnas.org.cn,填写实验室认可申请,按照要求上传附件,确认无误后提交。
第4步:文件审查:CNAS评审组会对材料进行文件审查,可能会指出不合理或者有疑惑的地方,需要进行补正。
第5步:预约评审:CNAS会安排评审组长和评审员,对实验室进行现场评审。
第6步:现场评审:评审老师会带着样品及盲样来到现场,进行观察实验。
第7步:整改验收:需要时,不符合项的整改验收。
第8步:批准发证:评定,批准,颁发认可证书。
第9步:后续工作:获得实验室CNAS认可后的监督和复评审。
CNAS认证的作用:
1.表明实验室具备了按有关国际认可准则开展检测和 (或)校准服务的技术能力;
2.增强实验室的市场竞争能力、赢得政府部门及社会的信任;
3. 获得了与CNAS签署互认协议的国家与地区实验室认可机构的承认 ,有利于消除非关税贸易技术壁垒;
4.参与国际间实验室认可双边、多边合作, 促进工业技术、商贸的发展;
5.可在认可的业务范围内使用“中国实验室国家认可”标志;
6.列入《国家认可实验室名录》,提高实验室知名度;
7.取得了占领检测和(或)校准市场的主动地位 ,获得更高的经济收益。
1. 创建项目工程及代码编写(Windows平台) 首先创建项目文件(文件名hello),并用VScode打开,进行项目编程。项目结构如下:
“避坑说明:头文件名称不要设置为include,会识别不到,报错”
对应文件代码如下:
头文件 print.h
#ifndef _PRINT_H_ #define _PRINT_H_ #include <iostream> using namespace std; void print(); #endif 源文件 print.cpp
#include "print.h" void print() { cout << "hello world!" << endl; } 源文件 main.cpp
#include <iostream> #include "print.h" using namespace std; int main() { print(); //cout << "hello, VScode!" << endl; return 0; } CMakeLists.txt文件
#规定cmake的最低版本要求 cmake_minimum_required (VERSION 3.10) #设置c++编译器 set(CMAKE_CXX_COMPILER "g++") #项目的名称,可以和文件夹名称(HELLO)不同 project(Cmake_print) #添加头文件的搜索路径 include_directories(${PROJECT_SOURCE_DIR}/header) #将源文件列表写在变量SrcFiles中 aux_source_directory(./src SrcFiles) #设置可执行文件输出路径 set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) #设置可执行文件的名称,make之后bin目录下出现myprint.
BeanFactory 说明: spring容器的底层接口,可以根据bean定义的信息,返回对应的实例对象,支持整个sring的生命周期流程。
提供的方法:
FactoryBean 说明: 就是一个简单的对象工程,实现了此接口的方法在整个bean周期中,可以使用自定义的方式来创建对象,而不需要进行默认的bean流程的创建。
提供的方法
使用
public class MyFactoryBean implements FactoryBean<Person> { @Override public Person getObject() throws Exception { Person person = new Person(); person.setName("张三"); person.setAddress("上海市上海"); return person; } @Override public Class<?> getObjectType() { return Person.class; } @Override public boolean isSingleton() { return true; } } 当我们使用时,如下就可以获取到对应的Person对象
public static void main(String[] args) { ApplicationContext bf = new ClassPathXmlApplicationContext("beanFactory.xml"); // 直接就可过去到对应的Person对象 Person person = (Person) bf.getBean("myFactoryBean"); } 这时细心的同学不知道有没有发现,那我需要怎么获取对应的myFactoryBean对象呢?
人狠话不多,直接上命令。
###################################################
### OS Preparation, CentOS v7-2009
###################################################
yum install -y telnet vim net-tools open-vm-tools wget ntpdate yum-utils device-mapper-persistent-data lvm2
ntpdate time.windows.com
systemctl stop firewalld
systemctl disable firewalld
sed -i 's/enforcing/disabled/' /etc/selinux/config
setenforce 0 swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system
###################################################
### Prepare yum repos from aliyun.com
###################################################
cat >> /etc/yum.repos.d/docker-ce.repo <<EOF
[docker-repo]
name=Docker Repository
Keywords: data redundancy, data privacy, data consistency, data integrity, data dependency, search & query
Data redundancy: the same data stored more than once. It's common that there are several copies of files so that the data can be shared to different people. This increases the data redundancy. One of the primary aims of the data base approach is the elimination of data redundancy.Data privacy: one problem of file-base approach is lack of data privacy.
文章目录 一、递归反转整个链表二、反转链表前 N 个节点三、反转链表的一部分25. K 个一组翻转链表 一、递归反转整个链表 力扣第 206 题「 反转链表」
迭代:
class Solution { public ListNode reverseList(ListNode head) { ListNode pre=head; ListNode post=null; while(pre!=null){ head=pre; pre=pre.next; head.next=post; post=head; } return head; } } 递归:
// 定义:输入一个单链表头结点,将该链表反转,返回新的头结点 ListNode reverse(ListNode head) { if (head == null || head.next == null) { return head; } ListNode last = reverse(head.next); head.next.next = head; head.next = null; return last; } 详细解释一下这段代码。
对于递归算法,最重要的就是明确递归函数的定义。具体来说,我们的 reverse 函数定义是这样的:
系列文章目录
历史文章1
文章目录 前言一、环境信息二、搭建步骤1.准备前置条件1.1 安装Docker1.2 拉取镜像 2.安装Etcd2.1 新建目录2.2 编辑脚本2.3 执行部署 三、结果验证在这里插入图片描述 总结参考 前言 本文介绍使用docker搭建一个etcd集群,附带对应的搭建脚本。我极力希望讲操作步骤和原理说明的尽量详细,能够让读者更容易理解。
一、环境信息 使用本地的vmstation创建3个虚拟机,信息如下
节点名称节点IP节点配置操作系统Etcd版本Docker版本etcd1192.168.82.1281c1g 20gCentOS7.4v3.513.1etcd2192.168.82.1291c1g 20gCentOS7.4v3.513.1etcd3192.168.82.1301c1g 20gCentOS7.4v3.513.1 说明:服务器应该能够访问公网,以便能够下载对应的etcd镜像
二、搭建步骤 1.准备前置条件 1.1 安装Docker 代码如下(示例):
# 安装docker yum install -y docker # 重启docker systemctl restart docker # 验证docker docker ps 备注,需要关闭防火墙
systemctl stop firewalld.service systemctl disable firewalld.service 1.2 拉取镜像 代码如下(示例):
# 拉取镜像 docker pull quay.io/coreos/etcd:v3.5.0 # 验证镜像 docker images|grep etcd 2.安装Etcd 2.1 新建目录 分别在3台机器上都新建目录 /data/etcd,用于挂载到容器中,能够讲etcd的数据持久化到本地磁盘。需要注意的是,再生产环境中尽可能的将etcd的数据目录单独挂载一个磁盘,磁盘的io性能越快越好。磁盘的io带宽尽量需要保证在40MByte/s以上。否则etcd会因为磁盘性能差,导致不断的切主或者无法完成基础的wal&snapshot写入,导致整体集群异常
2.2 编辑脚本 保存如下命令到脚本/data/start.sh,用于搭建etcd集群
[作者:张赐荣]
获取喜马拉雅音频直链的方法
对以下地址发起Request Get请求,返回Json格式结果,其中的data.src就是音频的真实路径。
"https://www.ximalaya.com/revision/play/v1/audio?ptype=1&id=soundID"
参数为sound id。
例如以下音频地址:"http://www.ximalaya.com/43755913/sound/355188898"
取"/sound/"候面的一串数字,得到音频ID"355188898"
形成请求地址:"https://www.ximalaya.com/revision/play/v1/audio?ptype=1&id=355188898"
返回JSON
{"ret":200,"data":{"trackId":355188898,"canPlay":true,"isPaid":false,"hasBuy":true,"src":"https://aod.cos.tx.xmcdn.com/storages/b35f-audiofreehighqps/3B/2A/CMCoOSIDhXNVARUyWwBm3Gnh.m4a","albumIsSample":false,"sampleDuration":180,"isBaiduMusic":false,"firstPlayStatus":true,"isVipFree":false,"isXimiAhead":false,"isAlbumTimeLimited":false,"ximiVipFreeType":0,"joinXimi":false}}
以下PHP代码封装了获取喜马拉雅音频直链地址的函数,传入音频ID(URL sound 之后的那串数字)即可
<?php
echo(GetLink("355188898"));
function GetLink ($sid)
{
$gc_url="https://www.ximalaya.com/revision/play/v1/audio?ptype=1&id=".$sid;
$gc_ch = curl_init();
curl_setopt($gc_ch, CURLOPT_L_VERIFYPEER, FALSE);
curl_setopt($gc_ch, CURLOPT_L_VERIFYHOST, FALSE);
curl_setopt($gc_ch, CURLOPT_REFERER,$gc_url);
curl_setopt($gc_ch, CURLOPT_URL,$gc_url);
curl_setopt($gc_ch, CURLOPT_USERAGENT,'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36 Edg/88.0.705.81');
curl_setopt($gc_ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($gc_ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($gc_ch, CURLOPT_HEADER,0);
$gc_content = curl_exec($gc_ch);
curl_close($gc_ch);
$resultObject=json_decode($gc_content);
return($resultObject->data->src);
}
?>
一、形参和实参 简单来说,形参用于实现,实参用于调用
void add1(int x,int y) { y=x+10; cout<<"add1(函数内): "<< y <<endl; } int main() { int a=10; int b=7; add1(a,b); // a,b作为 cout<<"add1: "<<b<<endl; } 输出:
add1(函数内): 20 add1: 7 以这段代码为例,上面void中的x,y就是形参,下面的a,b就是实参
形参和实参可以同名,比如我把void中的x,y都换成a,b。但为阅读方便一般不这么做。
形参的改变不会影响实参。比如上面的代码中,相当于把a和b复制一份扔进函数add1中。因此函数内的y的值会变,但b的值不会变
二、如何改变b 上面的代码展示了实参与形参的区别,但实际工作中我们经常需要对b进行修改,那么如何进行修改呢?
一般来讲有两种方法。方法1是将b的输入转为引用,另一种是转为指针
#include <iostream> using namespace std; void add1(int x,int y) { y=x+10; cout<<"add1(函数内): "<< y <<endl; } void add2(int x,int &y) { y=x+20; cout<<"add2(函数内): "<< y <<endl; } void add3(int &x,int &y) { y=x+35; cout<<"
文章目录 物超所值思维导图精华荟萃参考文献 物超所值 之前有猎头跟我聊天,说是正在看运营方面的书,觉得对自身的成长大有裨益,推荐我有空也学习一下运营知识。细细想来,人其实和一款产品并没有差很多,从出生时的一张白纸,通过自身的学习和环境的磨练不断改进和迭代,逐渐成熟稳重,展现价值,但最终也要走向衰败和死亡,消失在历史的长河中。只不过,在这个过程中,运营的主要负责人就是自己。我是希望能不虚此生的,所以有想过借用运营的方法论,对自己的未来进行卓有成效地运营。由此,运营的概念在我心里算是扎了根。此外,我最近也很热衷于维护自己现在的这个博客,在内容运营的方法论上,也有系统性学习的需求。
基于以上两点,我开始了《运营之光:我的互联网运营方法论与自白》的学习。整体来说,书中的内容浅显易懂,我之前从没接触过运营的任何知识,但读起来非常流畅,毫不费力。事实上,从语言和用词来看,该书甚至是有些过于口语化的。不过,这并不影响我对该书的大加赞赏。
首先,它对运营的剖析十分全面,从运营本身的定义和分类、运营行业的价值观、内在规律和方法论,以及运营人的职业规划都有较为深刻的描述。更有意义的地方在于,这些内容都是作者通过自己多年的工作经验,不断思考和提炼出来的。在读书的过程中,我能深切地感受到,作者对运营这个职业的热爱。我不太懂运营这个行业,但是这本书给我提供一个很舒服的姿势,去一窥其中的门道。
其次,本书虽然是一本运营的专著,但是其中的很多内容,都可以类推到其他地方,特别是对于行业本身和个人成长的深度思考。在看书的同时,会引导我会去反思运筹优化这个职业本身:如何定义运筹优化这个职业?做运筹优化的快乐源泉/价值体现在哪?是否存在什么职业规律?有哪些职业方向?每个方向是否具有一些特殊的侧重点?同时,我也还会站在运筹优化从业者的角度去思考:我们应该具备什么样的基础素质和什么样的思维模式?应该秉持什么样的职业价值观?如何打造自己的核心竞争力?以及如何做好自己的职业规划?当然,这其中的很多问题,是难以在一两天甚至一两个月就能有标准答案的,我目前理解的程度还比较浅,就不在这里丢人现眼了。不过跟着作者的思路,确实让我重新审视了运筹这个行业,对自己的未来发展也有了更加深度的思考。我相信,对大部分读者来说,这本书能在很多地方,启发大家去做延伸思考。
最后,通过这本书,我思考了博客运营的成功基础。博客的核心打动力,往往来自于博主个人极度细致入微和深度的经历、体验和思考;要把内容当做一种“与读者交朋友”的形式,还要围绕博主发自内心相信的、喜欢的东西来做内容,让内容与个人,尽可能是“合一”的。在这方面,我认为自己是有优势的。我所经历过的起起落落,数不胜数。学业上,体验了大学提前毕业的辉煌,也遭遇了最长的博士生涯;生活中,因为资金周转问题,看尽了人间的冷眼,却也在最低谷时刻,见证了人性的光辉。我经常自嘲说,我是读了两个博士学位,一个是技术的,一个是心理的。黑暗之中,仍不忘光明。对比思考,更容易产生质的升华。我个人终于完成了自我的救赎和蜕变,也成为了身边人咨询的热门对象。很喜欢作者的这句话——“是什么曾经拯救过你,你最好就用他来更好地拯救这个世界”。在帮助他人的事情上,我乐在其中,但不知足。我还希望,能通过博客的形式,以自己的见解,去帮助更多的人。
在具体的方法论方面,我也学到了很多。博客的定位和调性是需要首先被明确的,此外还需要关注三个点:内容的生产,内容的组织和包装,内容的流通。解决内容生产很难保证按期完成的两个小方法:学会收集灵感;先明确内容框架,再逐次填充细节;在长期内容的规划上,一个有效的策略就是常规内容保底、爆款内容重点突破。
总之,对于任何一个有抱负有理想的咸鱼来说,这本书是值得五星推荐的。
推荐的核心理由:它有助于启发你对自己职业的深度思考。
思维导图 歪歪了半天,都还没有说这本书都有哪些内容。本节按照我个人的理解,绘制了一张思维导图,供大家参考。
精华荟萃 本节整理书中触动我较深的部分内容。
写这边书的原因:是什么曾经拯救过你,你最好就用他来更好地拯救这个世界。
特征名称详细内容基本定义为了帮助产品与用户之间更好地建立起来关系,我们所需要使用的一切干预手段。模块分类内容运营、用户运营、活动运营、产品运营、其他特别运营,如新媒体运营、微信小组运营等.职业价值观唯有爱与用户不可辜负、要在用户面前找到一种不卑不亢的感觉、
只有你接受了你的产品,才能把它推荐给你的用户、要基于触动逻辑来与用户做朋友。价值体现你在创造一个小世界,并令人在其中获得愉悦。行业规律带着短视的线性思维投入运营工作中,往往很难做好运营;
一款产品在其早起过于关注用户增长,甚至出现爆红等现象,往往反而会加速其死亡;
早期产品的运营,一定要围绕着口碑来进行。 互联网的下一个时代是驱动运营:互联网在国内的发展,可以粗略被分成3个阶段:互联网发展的最早期,概念驱动时代;互联网发展的成长期,产品驱动时代;运营驱动时代。在这种情况下,很多产品的体验和业务流程,可能都会变得越来越同质化,越来越差异不大。于是,决定一个产品是否能够在竞争中脱颖而出的,可能就会越来越变成了:运营。
“市场”和“运营的区别”:市场所做的事情,主要瞄准着扩大品牌、产品的用户认知和提升产品的无形价值,比较务虚。相对而言,“运营”在做的事情更加务实一些,任何一件运营在做的事,一定需要落实到相应产品数据上,比如流量、注册用户量等。
“产品”和“运营”的关系:产品负责界定和提供长期用户价值,运营负责创造短期用户价值+协助产品完善长期价值。
做内容运营,首先需要确定内容的定位和调性,明确哪些内容可以写,哪些内容不能写,并给内容打上某种风格化的标签。此后还需要关注三个点:内容的生产,内容的组织和包装,内容的流通。解决内容生产很难保证按期完成的两个小方法:学会收集灵感;先明确内容框架,再逐次填充细节;在长期内容的规划上,特别常见的策略就是常规内容保底、爆款内容重点突破。
在内容运营方面,应该相信:内容本身的最大亮点在于其通过持续内容输出面向用户构建起来的某种强烈的“信任感”;内容的核心打动力,往往来自于内容生产者不同于他人的、极度细致入微和深度的经历、体验和思考;你应该把你的内容当做一种“与读者交朋友”的形式;你更应该围绕你发自内心相信的、喜欢的东西来做内容,让你的内容与你的人,尽可能是“合一”的;一个做内容的人,其个人价值会与他依靠内容获得用户认可的能力成绝对正比,而只会与他依靠内容吸引用户眼球的能力成阶段性正比。新媒体或者做内容这件事可能并不适合所有人,它需要对内容有所热爱,更适合那些时常能够有所感触、有所思考、喜欢表达的人。
绝大部分产品的运营工作如何规划,都可以从如下三个维度分别来评估:商业逻辑、典型用户行为频次、用户与其他用户间是否会通过你的产品而形成某种关系。
在理解互联网是什么时,由浅入深的4个回答:互联网是一种降低成本、提升效率的工具;互联网是一种新的充分用户变化的思考方式,这里是错成本较低,成功越来越属于变革者和拥抱变化者;互联网连接一切,赋予更多的人自由和平等;互联网是一种相信这个世界会变得更好的信仰。
参考文献 黄有璨.运营之光:我的互联网运营方法论与自白[M].电子工业出版社.2016.09.
做一个卡牌游戏,有一个需求,需要在for循环中延时执行一些逻辑。
期初用了cc.tween.delay(时间).call(回调函数)的方式,发现不行。
后来想起来可以用setTimeout来解决,正解。
但是使用setTimeout是有坑的,不能直接像下面这么写,否则延时函数里的i是不对的。
for(let i=0;i<5;i++){ setTimeout(function () { console.log('---------------'+i); }, 1000); } 可以通过在构造一个函数的方式,就可以解决,如下:
private testFor(){ for(let i=0;i<5;i++){ this.testDelay(); } } private testDelay(){ setTimeout(function () { console.log('---------------'+i); }, 1000); }
【SMB】windows 配置访问 smb 服务器 windows 如何访问 SMB 服务器,大致有以下几种方法,建议采用第三种方式:
使用 windows 系统自带的 smb 客户端进行访问
通过 windows 自带的smb客户端进行访问的方式不可取,在勒索病毒事件后 ,445端口被禁用了,而 windows smb客户端默认访问445端口,因此使用该方法必然不可行
使用代理的方式进行访问(不建议使用)
Samba:基于公网 IP 的服务访问
采用以上方式配置代理进行访问 SMB 服务器,成功访问,但是在停止 LanmanServer 后,关联的 Server 被停止,导致如果安装 Docker ,那么 Docker 的服务也被停止,而启动 LanmanServer 后,访问 SMB 服务器又不成功,具有一定的局限性
使用 SSH 协议方式进行访问(建议使用)
安装 winscp 连接远程服务器,可通过winscp 官网 下载进行安装,这篇安装过程可以作为一个参考
关于访问中文名文件出现 WinSCP错误:936(ANSI/OEM-简体中文GBK) 的解决方式
WinSCP错误:936(ANSI/OEM-简体中文GBK)
至此,windows 访问 smb 服务配置完成。如果介意使用 SSH 协议进行连接访问,那么可以采用第二种方式。
#MYSQL数据库到VUE前端架构
##==MYSQL数据库==
1. 安装--配置my.ini,通过DOS初始化mysql,开启mysql服务,加设置账号密码
2. Sql操作分类: 
3. DDL: 创建数据库create database 数据库名称 [库选项];删除数据库drop database 数据库名称;查看所有数据show databases;查看部分数据库show databases like "匹配模式";选择数据库use 数据库名称;查看选择的数据库select database();修改数据库选项alter database 数据库名称 新的库选项;
4. 数据类型:数值int,BIGINT,FLOAT,DOUBLE;日期和时间:DATE,DATETIME,YEAR;字符串类型:CHAR(存储性能高,但是浪费空间),VARCHAR(存储性能低,但是节约空间)
5. DML增删改查:(insert,delete,alter,select)ALTER TABLE 表名 RENAME TO 新表名; 改名
ALTER TABLE 表名 add 列名 数据类型; 增加一列
ALTER TABLE 表名 modify 列名 新数据类型; 修改数据类型
ALTER TABLE 表名 change 列名 新列名 新数据类型; 修改数据类型和列名
ALTER TABLE 表名 drop 列名 ; 删除一列
INSERT INTO 表名(列名1,列名2) VALUES(值1,值2) 给指定列加数据
INSERT INTO 表名(列名1,列名2) VALUES(值1,值2) 给指定列加数据
Evolving Losses for Unsupervised Video Representation Learning 这篇论文把非监督学习定义成一个多模态,多任务的学习,希望结合不同非监督学习的学习方法来综合学习到一个好的特征。
Intuition 如何构造定义这个unsupervised learning这样一个问题,以及为了达成这样的任务,中间解决了哪些问题?
首先本文想要学习到一个好的video representation,那什么样的represention是一个好的video representation呢?这里作者把他定义成了一个Multi modality 和multi tasks这样的任务。其实这是很好理解的,我们人单看这个画面,就可以知道这是一个体育场馆比赛游泳,我们通过这个画面也能自动脑补出会场的声音,以及下几秒伴随着游泳枪响运动员们开始有用,所以这些模态信息,我们人只需要看到一副图片是都可以脑补推导出来的。那么作者就像我能不能训练一个网络,像人一样只需要看到一张图就能想到这么多东西,可以包括未来声音的representation,下一帧图片等等,这样子就能学到一个好的representation,用来解决后续动作识别等等这样的问题。
所以作者把这个问题定义成了molti-modality,比如声音,RGB彩色图像,光流,灰色图像等等等等不同形式。但是这样又会带来另一个问题,那就是我们如果把self-supervised或者说unsupervised这些loss都加到最后一个大的loss function中,对于超参数的调整来说,将是一个灾难:
这里对于每一个modality,每一个task,都需要给他分配一个hyperparameyer来调整这个loss在整个loss function中的权重,这是一个非常闹心的任务,那么于此同时,作者还希望从一帧图像中解出这些所有的信息,我们把从其他网络,从声音网络,从灰度网络,从光流网络,他们这些网络中的这些embedding,这些representation都集成到RGB网络中,其实这是相当于蒸馏的过程。那么这同样也是一堆loss,一堆hyperparameters,那么为了调试这些这么多的hyperparameters,作者就想到能不能使用Evolving loss使用最优化手段,来让计算机帮我们搜寻出一个好的combination来把这些loss组合起来,这个想法是很自然的,但是我们又如何来评估我们得到这个loss的质量呢?当然我们想到的最好的方法是拿这个loss function去训练一个模型,然后再去测试集测试后面的表现不就可以估计出这个loss function的质量了吗?但是我们再学习过程中是不能使用task先验,就是我在学习过程中必须自己能够找到一种方法来评价我当前的模型质量,那么这个也是本文的贡献之一,就是**Evaluate fitness,**解决了这个问题之后,这篇论文的逻辑的链条就串起来了。
就是我在拿到许多视频之后,我们把它变成Multi modality,然后进行multi tasks的unsupervised的,那么这个学习的重点就是找到一个好的loss function,为了找到一个好的loss function,它的本质就是找到一个修改不同hyperparameters来得到这个loss function的fitness,来评价这个loss function的好坏,使其不断进化出一个好的loss fuction。最后拿出最好最后进化的loss function去训练大的模型,训练这个multi-modality,multi tasks这样一个模型。从而获得最终的latent representation。
那么这张流程图呢就是反映了本文定义的multi modality,multi task这样一个任务的过程。如图使用的光流,RGB,视频的声音,把这些不同的modality送到encoder里面,然后使用encoder学到的representation去执行不同的任务,同时呢我们把光流和声音网络学到的信息通过蒸馏的方式蒸馏到中间的RGB的网络中,最终我们就会得到一个强的latent representation而且还包含着其他网络的信息,这个信息就是一个非常强的能够帮助我们进行动作识别的representation。
Self-supervised tasks Self-supervised tasks包含了哪些任务呢?
Reconstruction and prediction tasks 1.Reconstruc input frame比如我们训练VAE或者Auto-Encoder的时候,输入一个图像然后把它重建出来。
2.Rredict the next N frames given T frames还有就是Prediction,输入T张图像之后使它预测未来的N张图像,这就要求我们的latent representation必须足够抽象,也能够学到视频在时间序列上的相关信息。
3.Cross-modality transfer tasks比如灰度图变彩色图,光流图变彩色图这样的任务。
以上三个或者总之与Reconstruction and prediction tasks的任务我们都可以使用reconstruct frame与ground truth之间的L2loss,来训练self-supervised task。
Abstract 就是将GAN和对比学习模块结合起来,对比学习不是需要数据增强吗,就用GAN的视图生成器来做这个增强,还提出了一种对比学习的损失函数,实验也证明取得了SOTA。
Introduction ReID的目标是从不同视图中识别物体,也即是根据可视化相似度从gallery中识别query,gallery和query其实就是对比学习中的两个试图,也是一大一小数据集和样本这样的一个关系。直白一点就是左边是传统对比学习的方法,只不过右边用GAN来代替数据增强的这种方法。。
这个生成器不是普通的生成器,作者先从无标签的数据集上生成了一种网状结构,之前的方法总是忽视这个人身材,这种网就可以联合得恢复身材和姿势,然后这个生成器就可以生成非常好的视图。一旦得到新的视图,我们就可以设计一些基于对比学习的伪标签,结合我们提出的损失函数最大化原始视图和生成视图之间的相似度。
对比学习和GAN是一起一起训练的,这是一个相互促进的过程,可以提高生成的质量。
**1.**提出了一种联合模型,将对比学习和GAN结合在一起。
**2.**在这个模型的生成器部分使用了网结构,和之前的方法对比不仅能考虑到人的姿势还能考虑到人的身材。
**3.**在对比学习模块中提出了一种视图不变的损失函数。
**4.**克服了以前基于gan的无监督ReID方法的局限性,这些方法严重依赖于标记源数据集,并且SOTA。
The method View Generator 首先我们定义一个3D网络中的一个2D平面作为原始的基础平面Sori,我们分别旋转3d网络,并且继续随机选择一个二维投影作为一个新的平面Snew。其实目的就是使用3D模型旋转来模拟不同角度照相机。Sori,x,Snew分别得到的represention两两结合通过编码器得到两个表示,结合各自的判别器,其实也就是生成了两种数据。第一种网格和第二种数据的表示结合起来再次生成一个最终表示。
整个过程有如下几个优化目标:
1.视图的重构损失 2.特征的重构损失 3.GAN的对抗损失 最后相加就是这一阶段的总体优化目标 View Contrast 这里使用了memory bank,可以稳定伪标签和扩大负样本的数量,而且这个memory bank也是通过一个动量的方式去更新的。我们使用一种聚类的算法去生成伪标签,通过得到伪标签,我们可以定义正样本和负样本。给定一个图像x,我们从memory bank中随机抽取K个具有不同伪标签的实例和一个与x具有相同伪标签的实例表示fpos。f,fnew,fpos三个两两之间组成正样本对,fnew和K个实例组成负样本对。损失函数呢其实还是传统的InferNCE,因为正样本对有三组,三组之间两两互相结合,负样本对就那一组,三个函数嘛很简单,都加起来。因为最后是联合训练,所以再把上述两个加起来就是最后的损失函数。## Abstract
就是将GAN和对比学习模块结合起来,对比学习不是需要数据增强吗,就用GAN的视图生成器来做这个增强,还提出了一种对比学习的损失函数,实验也证明取得了SOTA。
Introduction ReID的目标是从不同视图中识别物体,也即是根据可视化相似度从gallery中识别query,gallery和query其实就是对比学习中的两个试图,也是一大一小数据集和样本这样的一个关系。直白一点就是左边是传统对比学习的方法,只不过右边用GAN来代替数据增强的这种方法。。
这个生成器不是普通的生成器,作者先从无标签的数据集上生成了一种网状结构,之前的方法总是忽视这个人身材,这种网就可以联合得恢复身材和姿势,然后这个生成器就可以生成非常好的视图。一旦得到新的视图,我们就可以设计一些基于对比学习的伪标签,结合我们提出的损失函数最大化原始视图和生成视图之间的相似度。
对比学习和GAN是一起一起训练的,这是一个相互促进的过程,可以提高生成的质量。
**1.**提出了一种联合模型,将对比学习和GAN结合在一起。
**2.**在这个模型的生成器部分使用了网结构,和之前的方法对比不仅能考虑到人的姿势还能考虑到人的身材。
**3.**在对比学习模块中提出了一种视图不变的损失函数。
**4.**克服了以前基于gan的无监督ReID方法的局限性,这些方法严重依赖于标记源数据集,并且SOTA。
The method View Generator 首先我们定义一个3D网络中的一个2D平面作为原始的基础平面Sori,我们分别旋转3d网络,并且继续随机选择一个二维投影作为一个新的平面Snew。其实目的就是使用3D模型旋转来模拟不同角度照相机。Sori,x,Snew分别得到的represention两两结合通过编码器得到两个表示,结合各自的判别器,其实也就是生成了两种数据。第一种网格和第二种数据的表示结合起来再次生成一个最终表示。
整个过程有如下几个优化目标:
1.视图的重构损失 2.特征的重构损失 3.GAN的对抗损失 最后相加就是这一阶段的总体优化目标 View Contrast 这里使用了memory bank,可以稳定伪标签和扩大负样本的数量,而且这个memory bank也是通过一个动量的方式去更新的。我们使用一种聚类的算法去生成伪标签,通过得到伪标签,我们可以定义正样本和负样本。给定一个图像x,我们从memory bank中随机抽取K个具有不同伪标签的实例和一个与x具有相同伪标签的实例表示fpos。f,fnew,fpos三个两两之间组成正样本对,fnew和K个实例组成负样本对。损失函数呢其实还是传统的InferNCE,因为正样本对有三组,三组之间两两互相结合,负样本对就那一组,三个函数嘛很简单,都加起来。因为最后是联合训练,所以再把上述两个加起来就是最后的损失函数。
第一次读综述不知道,其实用思维导图比直接读综述更好。而且这篇论文就像我的第一个课题的课本一样。
Abstract 这好像是一篇综述,就说SSL方法的表现都很好,并且能胜任很多downstream task,应用在视觉、NLP、还有图学习上。本文主要根据SSL的目标将SSL划分为3类:生成、对比、生成加对比(也叫对抗)。并且SSL为什么能work起来有更深的思考,最后简单的地讨论了SSL未来的方向。
Introduction 自监督学习好啊,在三个领域已经很强了,但是手动标签、泛化误差,虚假的相关性、对抗攻击有很强的依赖性。利用不同输入型号之间的相关性自动标签。自监督学习的特征有二:1.通过半自动的方式从数据本身获取标签。2.数据之间的相互预测。人们经常混淆自监督学习和无监督学习,首先自监督学习属于无监督学习,因为确实没有使用手工标签。然而真正的无监督学习主要方向还是检测这一类,例如聚类降维这些,但是自监督的主要方向是恢复,既然是恢复本质上又属于有监督。给出了一张图片来区分:
有监督学习:人为告诉他是牛。
无监督学习:啥也没有
自监督学习:从有相关信息的其他输入自行获取标签。而对比学习其实属于自监督学习的一种。自监督学习虽然不需要知道标签信息,就是知道是牛,但是还是需要知道那些是类似的那些是不同的,也就是人为指定的正负样本规则本身就是一种标签,其实本质上也是一种有监督学习。
最后这篇综述的贡献主要有三点:1.自监督学习的回顾。2.自监督学习的分类和方法。3.自监督学习方向。
Motivation of Self-supervised Learning end-to-end的定义首先得理解什么是非端到端,传统机器学习模型,输入并不是原始数据,而直接输入特征,其实有时候数据的特征提取往往比模型算法还要重要。端到端的意思就是输入原始数据,直接输出最后结果。其实也就是说,端到端将分步解决的中间步骤连接整合在一起,成为一个黑盒子,我能看看到的只是输入的数据和输出的结果,就是从数据的端,到了结果的端。数据做了预处理,比如图像裁剪,句子分词仍然属于端到端。所以端到端的学习需要非常少的先验假设。
SSL主要分为三类:
Generative:自编码器的重构
一、连接数据库 帮助类 package com.zking.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; /** * 连接数据库 帮助类 * @author Administrator * */ public class DBHelper { //注册驱动 static { try { Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); } catch (Exception e) { e.printStackTrace();//处理异常信息 } } //连接语句 private static final String url = "jdbc:sqlserver://sqlserver:1433;DatabaseName=T283"; //获得连接 public static Connection getCon() { Connection con = null; try { con = DriverManager.getConnection(url,"sa","123"); } catch (Exception e) { e.printStackTrace();//处理异常信息 } return con; } public static void close(Connection con,PreparedStatement ps,ResultSet rs) { try { if(con!
好久不写博客了,因为最近在准备面试,一共投了九家,腾讯、菜鸟、美团、京东、贝壳、哔哩哔哩、联想、字节跳到、百度。到目前为止,笔试了美团和京东,美团五道编程题,通过了三道,有一道写了一半,另一道没写。京东三十道选择,两道编程,通过了一道编程。但是一直都没有了后续,知道5.19号晚上八点多收到了联想的面试通知,5.20日下午两点半开始。以下是我的面经。
1、介绍自己
2、面试官说问点基础的吧,问我hashmap和hashtable的区别。我答介绍了hashmap的数据结构,回答上了两个,a、hashmap是线程不安全的,hashtable是在此基础上加了synchronized实现的。b、hashmap允许一个key为null,允许value为null而hashtable不允许。
3、了解gc吗?介绍以下gc。我说了下堆的结构,说了新生代使用的都是复制算法,老年代使用两种算法,标记清除和标记整理。又说了新生代和老年代各有三种垃圾回收器,还有一种g1垃圾回收器,说了gc是如何判断该对象是否该被回收,即可达性分析算法。介绍了可达性分析算法:有一些对象被称为GCroot对象,其他对象根据是否被GCroot对象直接或者间接引用,如果被引用就不回收,如果没有被引用就被回收。又介绍了GCroot对象包括哪些,a、虚拟机栈中引用的对象。b、本地方法栈中引用的对象。c、方法区中静态变量引用的对象。(刚刚翻了翻笔记确实也没错,但是根据我现在的了解,类的静态变量应该在1.8被移到了堆中,所以下次再回答这类问题直接说静态变量引用的对象)。d、我说我忘了。。。翻了翻笔记是常量引用的对象。
4、问我了解反射机制吗?我说了解,我说:就是通过类的class对象可以获取到类的信息,包括类的属性啊、类的接口啊、类的方法之类的,也可以通过它直接生成这个类的对象。
5、问我了解反射机制有哪些应用场景吗?我说jdk动态代理。
6、我看你简历上说了解springboot、那你能说一下反射机制在spring boot中有哪些应用场景吗?
我懵逼了,我开始嘴瓢,说我思考思考。。。过了会憋出了一个拦截器吗?纯瞎蒙,其实我知道它广泛应用在AOP中,但是我刚开始想那不是spring里的吗。听了我的回答,他说还有呢,我说类装载吗(嘴瓢,我现在都不知道自己咋想的),改口说是将对象装配到容器里的过程吗?我真的崩溃了,然后他见我答得磕磕绊绊,说到处都有。!!!!好吧。
7、问我数据库了解过哪些,我说熟悉mysql,他问我md了解过吗,我问mongodb吗?他说是的,我说没有系统的学习过,仅仅知道这个数据库。
8、(前面少写了一个)问我了解java的同步机制吗,我说知道,一个是synchronized关键字,还有一个是RenntrantLock,一个是基于jvm层面的,一个是JavaAPI层面的。synchronized是基于对象锁,对象头中的markword字段关联的monitor监视器实现的,每一个对象都关联一个monitor对象,通过操作系统提供的指令monitorenter和monitorexit实现堆monitor对象关联的一个Int变量进行加减操作,其实还是操作系统提供的同步机制。RenntrantLock是通过AQS和CAS实现的。继承了
abstractqueuedsychronized(事实上并不是继承关系,而是组合了AQS的实现类)通过他提供的一系列线程阻塞唤醒机制实现的,CAS是通过UnSafe类提供的原子性的cas操作。
9、面试官:我看你说你了解springcloud,介绍一下。
我说它是一个RPC框架,有一个eureka注册中心,模块可以在注册中心上注册,他能够监听这些服务模块的状态,我们可以在其他系统通过调用在注册中心上注册了的服务,通过feign远程调用,它底层其实还是利用了RestTemplate实现的。
10、面试官:嗯,那我问你一个场景,在这些分布式框架没有诞生之前,我们是通过什么方式去远程调用的?
我思考了一会,回答就是直接http访问这个系统里的。。。然后我看他没反应,我又想起来了进程间通信可以用socket编程,我就问了是用socket吗?他说就是通过url访问,跟我第一种说的一样,我看他的反应应该算我说对了。
11、问我英语水平怎么样,我说勉强过了四级。都笑了。他说我口语怎么样,我说我喜欢看美剧,还行,他说如果给你三分钟用英语做个自我介绍可以吗?我说额、、我百度翻译一下背一下还是可以的。他笑了笑,说我大概了解了。
12、数据结构与算法了解吗?
我说了解,学过。他问介绍一下快排。我说快速排序吗?他说嗯。我说取数组的第一个元素,后面的数跟他作对比,小于他的放左边,大于他的放右边,左边的数组在类似的,进行递归。
他点了点头。
13、问我那你知道快排的时间复杂度是多少吗?
我说n乘以logn。
14、后面就是让我问问他,有什么想了解的。我说我思考思考,说:就是在实际项目中redis一般搭几台,缓存一台。。。他笑了笑说不是让你问这些,是让你问我想了解一下这个面试过程啥的,我没时间解答这个问题,比如面试如果通过了接下来还有几场面试。哦哦哦,我说那如果过了接下来还有几场面试,他说两场。。。。最后告诉我一两个星期有结果。
总结:本人人生第一次面试,非常激动,开始前抽了两个烟。以上回答可能跟正确答案有出入,希望大家可以指正一下。面试过程只进行了17分钟,如果不算最后的过程应该只要十五分钟。我看别人联想的面经好像说对英语要求不低,所以懂得都懂,如今人多机会少,虽然整体面试过程感觉不错,但还是不要报太大希望有2面比较好。。
1.想要实现微信的语音播放需要在微信公众号后台下载微信同声传译插件,可以去微信服务平台搜索此插件并下载,指定对应的小程序号就行了。
2.下载完在 微信小程序后台--设置--第三方设置-- 插件管理-- 进入 微信同声传译详情 复制插件AppID 到 app.json 进行配置:
app.json:
"plugins": { "WechatSI": { "version": "0.3.5", "provider": "wx069ba97219f66d99" } } wxml:
<view class="wrap"> <textarea class='content' placeholder='请输入内容' value='{{content}}' bindinput='content'></textarea> <view class='box'> <button class="btn start" size="mini" bindtap='start'>开始</button> <button class="btn" size="mini" bindtap='end'>结束</button> </view> </view> js
//引入插件:微信同声传译 const plugin = requirePlugin('WechatSI'); //创建内部 audio 上下文 InnerAudioContext 对象。 const innerAudioContext = wx.createInnerAudioContext(); Page({ data: { content: '',//内容 src:'', // }, onReady(e) { innerAudioContext.onError(function (res) { console.
项目开发中:随着社会得发展,一些数据得可视化也随之增加,我为大家提供一套我在Vue项目开发中所利用Echarts地图开发的中国地图与世界地图源码呈上;
第一步:---下载 下载版本:低于5.x版本-5.x版本不携带有地图(cnpm install --save echarts@4.x)
查看下载是否拥有china(中国地图)、world(世界地图)
第二步:---配置 到man.js中引入Echarts以及它的china(中国地图)、world(世界地图)--此步完成后可在单组件直接进行使用地图
//echarts & 地图 // 引入echarts以及中国地图china.js import * as echarts from 'echarts'; import '../node_modules/echarts/map/js/china'; //引入中国地图 import '../node_modules/echarts/map/js/world.js' // 引入世界地图 Vue.prototype.$echarts = echarts; * 我是通过vue的开发插件 地址:(开发插件)直接性的挂载到了vue上以便重复直接使用与整理维护
//引入自己弄的echarts import Echarts from "./plugins/echarts" import '../node_modules/echarts/map/js/china'; //引入中国地图 import '../node_modules/echarts/map/js/world.js' // 引入世界地图 Vue.use(Echarts) 第三步: 在src目录下创建plugins此文件放置echarts图形
第四步: 此文件中用于放置echarts实例便于重复使用与便于后期维护(其它echarts图形也可如此)
源码:
//引入echarts import echarts from "echarts"; const install = function (Vue) { //Object对象方法 : Es5提供:defineProperties Object.defineProperties(Vue.prototype, {//Vue.prototype挂在vue原型身上 $charts: { get() { return { //中国地图 chinaMap: function (id, data) { // var dom = document.
设备环境:Ubuntu18.04 + ros melodic
相机:乐视相机(乐视遗产,和奥比中光的Astra Pro同方案,便宜)
1. 首先要安装一部分依赖
sudo apt install ros-$ROS_DISTRO-rgbd-launch ros-$ROS_DISTRO-libuvc ros-$ROS_DISTRO-libuvc-camera ros-$ROS_DISTRO-libuvc-ros
2. 我建议建立一个空的工作空间,供调试(当然,也可以放入自己原有的ros工作空间)
mkdir -p ~/astra_ws/src
3. 从github下载astra的包并安装(也可以ros命令安装,这里采用github下载再编译)
cd ~/astra_ws/src
git clone https://github.com/orbbec/ros_astra_camera
roscd astro_camera
sudo sh ./scripts/create_udev_rules
随后进行编译
cd ..
catkin_make --pkg astra_camera
4. 插上相机的USB线,再
lsusb
得到输出
Bus 001 Device 019: ID 2bc5:0502 # RGB模块
Bus 001 Device 018: ID 2bc5:0403 # 深度模块
根据本机信息修改launch文件
找到ros_astra_camera/launch文件夹下的astropro.launch进行修改
将默认的0x0501改为刚才lsusb得到的0x0502
修改launch无需重新编译,但需要source一下
5. 查看相机原始数据
source devel/setup.bash
roslaunch astra_camera astrapro.launch
正文: 2022最新iApp源码(破解ZIP密码)+已编译的成品,我自己测试了一下,简单的是可以获取到,但是太复杂的就没测试过了,有兴趣的自行去测试吧,上方图片就是演示图。
程序: lanzou.com/i0cyF0529tyf
图片:
1.右键(主页右边CentOS 7 64位)-管理-克隆
新建一个名为CentOS 7 64 位 的克隆文件夹存放CentOS 7 64 位 的克隆
等待克隆完成
成功克隆
2.修改配置
在原来的虚拟机查看主机名,输入vi /etc/hostname可修改主机名
编辑成功后按esc键 :键输入:wq保存退出,然后reboot重启虚拟机,主机名就更改了
输入ip a查看原来虚拟机ip地址:ens33下面俩行(192.168.137.140)
在克隆的虚拟机查看主机名,输入vi /etc/hostname可修改主机名
编辑成功后按esc键 :键输入:wq保存退出,然后reboot重启虚拟机,主机名就更改了
输入ip a查看克隆虚拟机ip地址:ens33下面俩行(192.168.137.115)
在原来和克隆的虚拟机上输入vi /etc/hosts 进去VI编辑模式点击 i 添加被克隆的虚拟机的IP地址与克隆后的虚拟机的IP地址(原来和克隆的都要)
克隆机上输入ping 192.168.137.140(在原来的虚拟机也可以操作,输入192.168.137.115)
Ctrl c 停止ping
可以看出两台主机互ping成功,如果写的不好欢迎大家批评指正。
通过本博客你将搭建的服务,以及配置如下:
0,用SeceruCRM连接服务器后台 1,设置linux字符编码 2,统一服务器时区 3,安装jdk环境 4,安装maven 5,安装tomcat 6,安装redis 8,安装mysql 9,安装svn 10,安装NgInx 11,安装jenkins 12,开放服务器指定端口 13,其他注意细节,避免采坑 需要的前置条件:
1,一台服务器 耗时:
4小时-16小时
好了,进入正题。。。。 【0,用SeceruCRM连接服务器后台】
先 创建一个会话,右键 new session 如下图 然后一直下一步即可,然后会提示你输入密码 连接成功如下图 然后我们来先设置一下SeceruCRM的显示的字符编码,如下图 【1,设置系统统一字符集】
查看当前系统编码locale
[root@izm5e88p52tbiop389kbojz ~]# locale LANG= LC_CTYPE="POSIX" LC_NUMERIC="POSIX" LC_TIME="POSIX" LC_COLLATE="POSIX" LC_MONETARY="POSIX" LC_MESSAGES="POSIX" LC_PAPER="POSIX" LC_NAME="POSIX" LC_ADDRESS="POSIX" LC_TELEPHONE="POSIX" LC_MEASUREMENT="POSIX" LC_IDENTIFICATION="POSIX" LC_ALL= 设置当前系统编码:export LANG=zh_CN.UTF-8
然后我们再次查看是否设置成功:locale
locale: Cannot set LC_CTYPE to default locale: No such file or directory locale: Cannot set LC_MESSAGES to default locale: No such file or directory locale: Cannot set LC_ALL to default locale: No such file or directory LANG=zh_CN.
目录
一、创建字符串的四种方式
1.直接赋值
2.通过构造方法创建对象
3.通过字符数组创建对象
4.通过String类的静态方法valueOf(任意数据类型)->转为字符串
二、字符串比较相等
.equals方法
.equalsIgnoreCase方法
判空处理
三、常量池问题
什么是常量池
常量池中的对象从何而来?
1.直接赋值产生
2.构造方法产生
手工入池:intern方法
例子:
1.
2.
3.
四、字符串的不可变性
五、修改字符串的内容
1.通过反射破坏value数组的封装
2.使用StringBuilder类或者StringBuffer类
二者的区别
创建方法:
方法使用:
六、字符串的其他常见操作
1.字符串比较
2.字符与字符串的相互转换
char->String
String->char
如何判断一个字符串是由纯数字组成的
3. 字符串和字节的相互转换
String->byte[]
byte[] ->String
4.字符串的查找操作
5.字符串的替换操作
6.字符串的拆分操作
以括号中的内容进行拆分,可指定拆分最大个数
当用到特殊字符时,我们可以用\\进行转义处理
7.字符串的截取操作
8.字符串的其他常用方法
写一个方法将字符串的首字母大写
String类算是比较特殊的类型了,作为初学者我们甚至把这个引用类型时不时当成基本类型来用,而且发现,竟然差不多。然而实际呢?我们太年轻,差的真的很多,今天就来详细讲一讲到底差在哪。
一、创建字符串的四种方式 1.直接赋值 直接赋值,在堆中的常量池中创建该字符串对象
String str1 = "HelloWorld"; 2.通过构造方法创建对象 在堆中创建对象,并把该对象的拷贝放到常量池中
String str2 = new String("HelloWorld"); 3.通过字符数组创建对象 首先创建字符数组,并且通过构造方法传入此数组来创建对象,此对象不入常量池
char[]data=new char[]{'a','b','c'}; String str3 = new String(data); 4.
MQ 概述: MQ 全称 message queue (消息队列) ,是在消息的传输过程中保存消息的容器。多用于分布式系统之间进行通信。
MQ 消息队列,存储消息的中间件
分布式系统的通信两种方式:直接远程调用和借助第三方完成间接通信
发送方称为生产者,接收放称为消费者
MQ 优势和劣势 优势:
应用解耦
异步提速
削峰填谷
劣势:
系统可用性降低:系统引入的外部系统越多,系统稳定性越差。一旦MQ 宕机,就会对业务造成影响。如何保证 MQ 的高可用?
系统复杂度提高:MQ 的加入大大增加了系统的复杂度,以前系统之间是远程调用的,现在是通过MQ 异步调用。如何保证消息没有被重复消费?如何处理消息丢失情况?如何保证消息传递的顺序性?
一致性问题:A 系统处理完业务,通过 MQ 给 B、C、D 三个系统发消息数据,如果 B 系统、C系统处理成功,D系统处理失败。如何保证数据处理的一致性。
常见的MQ 产品 目前叶节有很多的MQ产品,例如 RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ、MetaMQ 等,也有直接使用 Redis 充当消息队列的案例。
RabbitMQ 概述 AMQP, 即 Advanced Message Queuing Protocol (高级消息队列协议), 是一个网络协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同的开发语言等条件的限制。2006 年, AMQP 规范发布。类比 HTTP。
2007 年, Rabbit 技术公司基于 AMQP 标准开发的 RabbitMQ。RabbitMQ 采用 Erlang 语言开发。,专门为开发高并发和分布式系统的一种语言。
有很多虚拟服务器,完成了逻辑分区的功能。
Broker: 接收和分发消息的应用,RabbitMQ Server 就是 Message Broker
报错 在使用git clone时,报以下错误
remote: Counting objects: 5551, done. remote: Compressing objects: 100% (2178/2178), done. error: RPC failed; curl 56 OpenSSL SSL_read: Connection was reset, errno 10054 fatal: the remote end hung up unexpectedly fatal: early EOF fatal: index-pack failed 解决 1.输入命令
git config http.sslVerify "false" 2.如果出现
fatal: not in a git directory 3.需要git初始化该文件
git init 4.重新git clone,发现还是报错
remote: Counting objects: 5551, done. remote: Compressing objects: 100% (2178/2178), done. error: RPC failed; curl 56 OpenSSL SSL_read: Connection was reset, errno 10054 fatal: the remote end hung up unexpectedly fatal: early EOF fatal: index-pack failed 5.
cp -r dir1 rootdir
在项目开发中遇到了这样一种情况:
需要用一个干净的工程(export出来的,没有svn信息)去覆盖一个主干的工程(含有svn信息),然后提交代码;我们在mac系统中拷贝->粘贴到目标文件夹,只有2个选项:停止和全部替换;选择全部替换后,svn信息全部丢失了。
这时我们可以使用cp -r dir1 rootdir 来进行覆盖,dir1是那个干净工程的文件夹路径,和主干工程同名;rootdir是主干工程的上级目录,如此一来我们就实现了保留svn信息前提下覆盖文件夹的目的。
目录
string容器
基本概念:
构造函数:
赋值操作:
追加操作:
查找、替换操作:
删除、插入操作:
对比操作:
存放操作:
获取子串操作:
vector容器
构造函数:
赋值操作:
容器大小和容量操作:
容器的插入和删除:
存放操作:
互换容器操作:
预留空间操作:
string容器 基本概念: string就是C++中的字符串类型,它的本质还是一个类,它封装了一个char*类型的指针。就像我们C语言中用字符指针来维护字符串;C++中用封装好的类string来维护字符串类型。
构造函数: string容器可以有4种构造函数的使用方法:
1.调用无参构造:直接在字符串类型后面定义一个常量字符串;
2.调用有参构造:第一个参数传递字符串字符个数,第二个参数传递字符。可以构造重复字符字符串;
3.调用拷贝构造:直接往字符串类型里传一个字符串类型变量;
4.调用有参构造:传递一个const char*类型变量维护的字符串指针;
//字符指针维护的字符串类型; const char* s0 = "abced"; //字符串类型无参构造; string s1="abcde"; //字符串类型有参构造,第一个参数字符串的字符个数,第二个参数字符串的字符; string s2(5,'a'); //字符串类型拷贝构造; string s3(s1); //字符串类型有参构; string s4(s0); 赋值操作: 在string容器中,我们可以利用等号来赋值操作,也可以利用string里的assign成员函数来进行赋值操作;
“=”赋值:
1.直接赋值常量字符串;
2.赋值string类型;
3.赋值单个字符类型;
成员函数assign赋值:
1.赋值常量字符串;
2.赋值string类型;
3.赋值常量字符串前n个字符;
4.赋值n个字符x;
//等号赋值常量字符串; string s1; s1 = "hello"; //等号赋值string类型; string s2; s2 = s1; //等号赋值单个字符; string s3; s3 = 'a'; //assign函数赋值string类型 string s4; s4.
第三方服务内容:
需要学习通与激励系统
学习活动管理:
学生端:
两方面内容:
活动执行
主题讨论:是给人以思考的内容
随堂练习:填写选择题
调查问卷:调研生活与学习相关的内容
研究与挑战:学习了解知识
活动流程:
关于自动创建活动的内容 2.学情视图管理:
老师端:
参与度 词云 问题:累计记录与连续记录 3.行为记录管理:
针对行为记录的统计模块
回复主题讨论
激励策略管理:
1.激励管理:
效果:提示音与图片显示
配置:如果没有参与活动,通过MSG接口给钉钉发送调查问卷
2.规则管理:
业务关键字管理:延时
规则参数管理:延时次数与延时时间
内容管理
①颗粒库管理:
章节爬取:爬取软件中的章节名称
章节同步:将章节名称同步到数据库中
②.资源管理:
章节资源管理:将章节的活动内容进行爬取 活动资源管理:将章节活动内容存放数据库中 ③.班课执行颗粒管理:
顺序管理:设置章节活动的推送顺序
颗粒推送管理:将章节活动进行推送
教务管理:
1.学生管理:
2.教师管理:
实名认证
3.班课管理:
添加课程、更新课程、删除课程
关于一些软件的支持为:学习通、权限、MSG、钉钉
数据支持:redis、MySQL
在面向对象方面:
1.有些功能相似的业务需要用面向对象的思想来进行封装、继承、多态的思想去实现
2.减少前端代码,前端代码每一页的内容不超过200行,也可以用封装的思想
3.进行代码优化:设计模式要用在正确的地方, 要明确switch类型与if-else类型的代码之间的关系
在性能方面:
1.减少对数据库读取操作
2.提高内存,减少资源消耗
文章目录 TCP协议段格式TCP原理确认应答机制超时重传机制连接管理机制三次握手:四次挥手: 滑动窗口如果出现丢包,如何进行重传? 流量控制拥塞控制延迟应答捎带应答 粘包问题TCP异常情况 TCP,即Transmission Control Protocol,传输控制协议,对数据的传输进行详细的控制。 TCP协议段格式 源/目的端口号:表示数据从哪个进程来,到那个进程去。
源端口号表示报文的发送端口,源端口号和源IP地址组合起来可以表示报文的发送地址。
目的端口表示报文的接收端口,目的端口和目的IP地址组合起来可以表示报文的接收地址。
TCP协议就是根据IP协议的基础上传输的,TCP报文中的源端口号+源IP,与TCP报文中的目的端口号+目的IP一起,组合起来唯一性的确定一条TCP连接。
序号(Sequence Number):TCP传输过程中,在发送端出的字节流中,传输报文中的数据部分的每一个字节都有它的编号。序号(Sequence
Number)占32位,发起方发送数据时,都需要标记序号。
在数据传输过程中,TCP协议通过序号(Sequence
Number)对上层提供有序的数据流。发送端可以用序号来跟踪发送的数据量;接收端可以用序号识别出重复接收到的TCP包,从而丢弃重复包;对于乱序的数据包,接收端也可以依靠序号对其进行排序。
序号会根据SYN是否为1,表示不同的意思:
当SYN为1时,当前为建立连接阶段;
当SYN为0是,数据传输正式开始。
确认序号(Acknowledgment Number):确认序号标识了报文接收端期望接收的字节序列。如果设置了ACK控制位,确认序号的值表示一个准备接收的包的序列号,注意,它所指向的是准备接收的包,也就是下一个期望接收的包的序列号。
4位TCP报头长度:表示TCP头部有多少个32位bit(4字节);所以TCP头部最大长度为 15 * 4 = 60字节。
6位标志位:
URG:紧急指针是否有效;ACK:确认号是否有效,ACK置 1 ,代表起到了确认作用,需要填写确认序列号(下一次期望收到第一个字节的序列号);PSH:提示接收端应用程序立刻从TCP缓冲区把数据读走;RST:对方要求重新建立连接,我们把携带RST标识的称为复位报文段;SYN:请求建立连接,我们把携带SYN标识的成为同步报文段;FIN:通知对方,本端要关闭了,我们称携带FIN标识的为结束报文段。 窗口大小:长度为16位,共2个字节。此字段用来进行流量控制。流量控制的单位为字节数,这个值是本端期望一次接收的字节数。
16位校验和:发送端填充,CRC校验。接收端校验不通过,则认为数据有问题,此处的检验和不光包含TCP首部,也包含TCP数据部分。
16位紧急指针:标识那部分数据是紧急数据。
TCP原理 TCP对数据传输提供的管控机制,主要体现在两个方面:安全、效率。
这些机制和多线程的设计原则类似:保证数据传输的安全前提下,尽可能地提高传续效率。
确认应答机制 TCP将每个字节的数据进行了编号,即序列号。
每一个ACK都带有对应的确认序列号,意思是告诉发送者,我已经收到了那些数据,下一次你从哪里开始给我发。
超时重传机制 主机A给主机B发送了数据之后,可能会因为网络拥堵等原因,数据无法发送到B,如果A在一个特定的时间间隔内没有收到B发来的确认应答,就会重新发送。
当然,A没有收到确认应答,也可能是ACK丢了。因此,主机B会收到很多重复数据,可以利用序列号做到去重的效果。
那么超时时间如何确定?
最理想的情况下,找到一个最小的时间,保证 “确认应答一定能在这个时间内返回”。
但是这个时间的长短,随着网络环境的不同,是有差异的。
如果超时时间设的太长,会影响整体的重传效率;
如果超时时间设的太短,有可能会频繁发送重复的包
TCP为了保证无论在任何环境下都能比较高效地通信,因此会动态计算这个最大超时时间。
Linux中(BSD Unix和Windows也是如此),超时以500ms为一个单位进行控制,每次判定
超时重发的超时时间都是500ms的整数倍。
如果重发一次之后,仍然得不到应答,等待 2500ms后再进行重传。如果仍然得不到应答,等待 4500ms 进行重传。依次类推,以指数形式递增。
累计到一定的重传次数,TCP认为网络或者对端主机出现异常,强制关闭连接。
连接管理机制 在正常情况下,TCP要经过三次握手建立连接,四次挥手断开连接
三次握手: 第一次握手:客户端进入SYN_SENT状态,发送一个SYN帧来主动打开传输通道,该帧的SYN标志位被设置为1,同时会带上Client分配好的SN序列号,该SN是根据时间产生的一个随机值。第二次握手:服务端在收到SYN帧之后,会进入SYN_RCVD状态,同时返回SYN+ACK帧给客户端,主要目的在于通知客户端,服务端已经收到SYN消息,现在需要进行确认。
服务端发出的SYN+ACK帧的ACK标志位被设置为1,其确认序号ASN值被设置为客户端的SN+1;SYN+ACK帧的SYN标志位被设置为1,SN值为服务端生成的SN序号。第三次握手:客户端在收到服务端的第二次握手的SYN+ACK确认帧之后,首先将自己的状态会从SYN_SENT变成ESTABLISHED,表示自己方向的连接通道已经建立成功,客户端可以发送数据给服务端了。然后,客户端发ACK帧给服务端,该ACK帧的ACK标志位被设置为1,其确认序号ASN值被设置为服务端的SN序列号+1。服务端收到客户端的ACK之后,会从SYN_RCVD状态变成ESTABLISHED状态,至此,TCP全双工连接建立完成。 四次挥手: 第一次挥手:主动断开方向对方发送一个FIN结束请求报文,此报文的FIN位被设置为1,发送完成后,主动断开方进入FIN_WAIT_1状态,这表示主动断开方没有业务数据要发送给对方,准备关闭SOCKET连接了。第二次挥手:正常情况下,在收到了主动断开方发送的FIN断开请求报文后,被动断开方会发送一个ACK响应报文,之后,被动断开方就进入了CLOSE-WAIT(关闭等待)状态,TCP协议服务会通知高层的应用进程,对方向本地方向的连接已经关闭,对方已经没有数据要发送了,若本地还要发送数据给对方,对方依然会接受。被动断开方的CLOSE-WAIT(关闭等待)还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。第三次挥手:在发送完成ACK报文后,被动断开方还可以继续完成业务数据的发送,待剩余数据发送完成后,或者CLOSE-WAIT(关闭等待)截止后,被动断开方会向主动断开方发送一个FIN+ACK结束响应报文,表示被动断开方的数据都发送完了,然后,被动断开方进入LAST_ACK状态。第四次挥手:主动断开方收在到FIN+ACK断开响应报文后,还需要进行最后的确认,向被动断开方发送一个ACK确认报文,然后,自己就进入TIME_WAIT状态,等待超时后最终关闭连接。处于TIME_WAIT状态的主动断开方,在等待完成2MSL的时间后,如果期间没有收到其他报文,则证明对方已正常关闭,主动断开方的连接最终关闭。
被动断开方在收到主动断开方的最后的ACK报文以后,最终关闭了连接。 为什么TIME_WAIT的时间是2MSL呢?