安装postgreSQL出现错误提示 configure: error: zlib library not found。
解决方法:yum install zlib-devel
详细过程如下:
[root@April postgresql-9.2.24]# yum install zlib-devel; Loaded plugins: fastestmirror, security Loading mirror speeds from cached hostfile * base: mirrors.163.com * extras: mirrors.163.com * updates: mirrors.163.com Setting up Install Process Resolving Dependencies --> Running transaction check ---> Package zlib-devel.i686 0:1.2.3-29.el6 will be installed --> Finished Dependency Resolution Dependencies Resolved =============================================================================================================================== Package Arch Version Repository Size =============================================================================================================================== Installing: zlib-devel i686 1.2.3-29.el6 base 44 k Transaction Summary =============================================================================================================================== Install 1 Package(s) Total download size: 44 k Installed size: 115 k Is this ok [y/N]: y Downloading Packages: zlib-devel-1.
harbor的安装方法网上有很多,就不写了,参考https://www.cnblogs.com/guyeshanrenshiwoshifu/p/9166195.html
下面记录配置外放访问的几点关键点
harbor.cfg文件的hostname配置为外网ip(网上一般配置的都是内网ip)
/lib/systemd/system/docker.service配置为ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
配置外网访问docker私有仓库不安全,如果不是必要还是配置内网的吧
# -*- coding: UTF-8 -*- """ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @File : knn.py @Contact : ffzzyy@126.com @License : (C)Copyright 2017-2019 @Author : ffzzyy @Version : 0.1 @Modify Time : 2019/3/13 22:51 @Desciption """ import numpy as np from sklearn import datasets from collections import Counter from sklearn.neighbors import KNeighborsClassifier class KNNClassifier: def __init__(self, k): assert k >= 1, 'k must be valid' self.k = k self._x_train = None self._y_train = None def fit(self, x_train, y_train): ''' 训练函数 :param x_train: :param y_train: :return: ''' self.
leetcode621:任务调度器 先看问题:解答思路代码:提交结果 先看问题: 给定一个用字符数组表示的 CPU 需要执行的任务列表。其中包含使用大写的 A - Z 字母表示的26 种不同种类的任务。任务可以以任意顺序执行,并且每个任务都可以在 1 个单位时间内执行完。CPU 在任何一个单位时间内都可以执行一个任务,或者在待命状态。
然而,两个相同种类的任务之间必须有长度为 n 的冷却时间,因此至少有连续 n 个单位时间内 CPU 在执行不同的任务,或者在待命状态。
你需要计算完成所有任务所需要的最短时间。
实例1:
输入: tasks = ["A","A","A","B","B","B"], n = 2 输出: 8 执行顺序: A -> B -> (待命) -> A -> B -> (待命) -> A -> B. 注:
任务的总个数为 [1, 10000]。
n 的取值范围为 [0, 100]。
解答思路 首先看到“大写的A-Z”时,我就想到应该可以用大小为26的数组来充当辅助数组,但之后却没有一个良好完整的思路,纠结无果后,去网上找了题解来看,这里来记录一下这道题,以供自己日后温习。
以 [“A”,“A”,“A”,“A”,“B”,“B”,“B”,“B”,“C”,“C”,“C”,“D”,“D”,“E”],n = 2,为例来进行说明。
首先用26大小数组来确定每个任务的数量,然后将数组进行排序,将数量最大的排到最后。由于任务是交替执行的,数量最多的任务必然应该安排到每个n的节点上以求达到最短时间,如图(其中“#”代表除A以外的其他字符):
A##A##A##A#… 这时可以看到ans至少等于(A的数量-1)*(n + 1)+ 1,其它数量小于等于A的字符就可以被安插在“#”的位置。这时数量等于A的字符必然会占到最后一个A后面“#”的位置,如下图的B,这时ans的数量就要加一:
AC#AC#AC#AC… 代码: class Solution { public int leastInterval(char[] tasks, int n) { int len = tasks.
1、数据的大小写转换:
toLowerCase()
toUpperCase()
2、浏览器参数传递:
在浏览器中经常需要给浏览器传递参数,其中我们需要对参数进行处理,其中一个就是去掉参数中的空格,因为空格可能会在浏览器中转换为其他的字符串,导致浏览器的参数获取不到。
利用trim() 即可实现此想法。
3、后面会继续增加用法。。。
iOS 开发的时候,我们需要打开某个网页,可以写一个web页面,也可直接使用浏览器打开网址
那么我们怎么样使用iOS 内置的浏览器打开网址呢?
如下:
ios 10 之前使用 [[UIApplication sharedApplication]openURL
openURL:打开的网址
NSURL *URL = [NSURL URLWithString:@"http://www.baidu.com"]; [[UIApplication sharedApplication]openURL:URL]; ios 9 以后使用 [[UIApplication sharedApplication] openURL: options: completionHandler: ];
这个函数异步执行,但在主队列中调用 completionHandler 中的回调
openURL: 打开的网址
options: 用来校验url和applicationConfigure是否配置正确,是否可用。
唯一可用 @{UIApplicationOpenURLOptionUniversalLinksOnly:@YES}。
不需要不能置nil,需要使用@{}为置空。
ompletionHandler:如不需要,可以置为nil
NSURL *URL = [NSURL URLWithString:@"http://www.baidu.com"]; [[UIApplication sharedApplication]openURL:URL options:@{} completionHandler:^(BOOL success { // 回调 }];
一般情况下,软件的漏洞信息和特定版本是相关的,因此,软件的版本号对攻击者来说是很有价值的。
在默认情况下,Apache Httpd 系统会把Apache版本模块都显示出来(http返回头信息)。如果列举目录的话,会显示域名信息,服务器版本号,操作系统类型等。
隐藏Apache版本号的方法是修改Apache的配置文件:
vim /etc/httpd/conf/httpd.conf
返回客户端头信息:
[root@ithomer conf]# curl –head 127.0.0.1
HTTP/1.1 200 OK
Date: Thu, 22 Jan 2015 15:39:00 GMT
Server: Apache/2.2.26 (CentOS)
X-Powered-By: PHP/5.5.9
Vary: Cookie,Accept-Encoding,User-Agent
X-Pingback: http://blog.mimvp.com/xmlrpc.php
Cache-Control: max-age=600
Expires: Thu, 22 Jan 2015 15:49:00 GMT
Content-Type: text/html; charset=UTF-8
上面头信息中,会显示服务器类型和版本(Apache/2.2.26),以及操作系统(CentOS)
修改 ServerTokens
修改 ServerTokens OS 为 ServerTokens productonly
重启 Apache : /etc/init.d/httpd restart
再次返回头信息如下:
[root@ithomer conf]# curl –head 127.0.0.1
HTTP/1.1 200 OK
Date: Thu, 22 Jan 2015 15:40:53 GMT
前言: 一般医学图像处理软件,
所使用的是QT来用作界面UI设计。
ITK进行算法的操作,例如分割。
但是ITK不能用于显示
所以就需要用VTK来显示等。
本例子是一个简单的整合
QT、VTK、ITK的一个Demo,
以供需要的人参考。
操作示例: 程序运行图:
QT版本:
项目属性页:
附录: 搭建好环境,程序可以运行。
这里可以检测下VTK和ITK是否配置好。
ITK测试程序:
#include "itkImage.h" #include <iostream> int main() { using ImageType = itk::Image< unsigned short, 3 >; ImageType::Pointer image = ImageType::New(); std::cout << "ITK Hello World !" << std::endl; return EXIT_SUCCESS; } VTK测试程序:
#include <vtkSphereSource.h> #include <vtkPolyData.h> #include <vtkSmartPointer.h> #include <vtkPolyDataMapper.h> #include <vtkActor.h> #include <vtkRenderWindow.h> #include <vtkRenderer.h> #include <vtkRenderWindowInteractor.h> #include "vtkAutoInit.h" VTK_MODULE_INIT(vtkRenderingOpenGL2); // VTK was built with vtkRenderingOpenGL2 VTK_MODULE_INIT(vtkInteractionStyle); int main(int, char *[]) { // Create a sphere vtkSmartPointer<vtkSphereSource> sphereSource = vtkSmartPointer<vtkSphereSource>::New(); sphereSource->SetCenter(0.
1. 环境准备 操作系统:Windows7
JDK版本:Java version "1.8.0_201"Gradle版本:Gradle 3.3ElasticSearch源码版本:Github branch 5.4(5.4分支代码内部实际ES版本为5.4.4)ElasticSearch发行版版本:elasticsearch-5.4.3(ES发行版没有5.4.4版本,此处使用5.4.3)Idea版本:IntelliJ IDEA 2018.3.5 x64 2. 下载和编译ElasticSearch源码 从Github下载ES源码:
#下载指定分支:5.4 $ git clone -b 5.4 https://github.com/elastic/elasticsearch.git 更换Gradle镜像源:使用Gradle原始镜像源,编译过程中下载相应依赖jar包速度太慢,此处我们更换为阿里的源。(对所有项目生效,在USER_HOME/.gradle/下创建init.gradle文件)
allprojects{ repositories { def ALIYUN_REPOSITORY_URL = 'http://maven.aliyun.com/nexus/content/groups/public' def ALIYUN_JCENTER_URL = 'http://maven.aliyun.com/nexus/content/repositories/jcenter' def GRADLE_LOCAL_RELEASE_URL = 'https://repo.gradle.org/gradle/libs-releases-local' def ALIYUN_SPRING_RELEASE_URL = 'https://maven.aliyun.com/repository/spring-plugin' all { ArtifactRepository repo -> if(repo instanceof MavenArtifactRepository){ def url = repo.url.toString() if (url.startsWith('https://repo1.maven.org/maven2')) { project.logger.lifecycle "Repository ${repo.url} replaced by $ALIYUN_REPOSITORY_URL." remove repo } if (url.startsWith('https://jcenter.bintray.com/')) { project.
目录 简介图解核心组件`API网关服务:Spring Cloud Zuul``声明式服务调用:Spring Cloud Feign``分布式配置中心:Spring Cloud Config`服务治理:Spring Cloud Eureka客户端负载均衡:Spring Cloud Ribbon服务容错保护:Spring Cloud Hystrix消息总线:Spring Cloud Bus消息驱动微服务:Spring Cloud Stream分布式服务跟踪:Spring Cloud Sleuth 工程使用版本 简介 Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。
图解 核心组件 API网关服务:Spring Cloud Zuul Zuul功能:认证、压力测试、金丝雀测试、动态路由、负载削减、安全、静态响应处理、主动/主动交换管理配置 zuul: ignored-services: '*' # 忽略配置 routes: zxjx-crm: /zxjx/crm/** 声明式服务调用:Spring Cloud Feign 可以理解为用户服务之间的调用,不经过api路由
使用@EnableFeignClients(basePackages = {“cn.xxt.zxjx.crm”}),开启Feign
注
扫描添加的微服务包被调用的API接口中参数必须使用@RequestParam中的value属性,指定参数名 分布式配置中心:Spring Cloud Config 实现了对服务端和客户端中环境变量和属性配置的抽象映射。由于Spring Cloud Config实现的配置中心默认采用Git来存储配置信息,所以天然就支持对服务应用配置信息的版本管理 服务治理:Spring Cloud Eureka 客户端负载均衡:Spring Cloud Ribbon 服务容错保护:Spring Cloud Hystrix 消息总线:Spring Cloud Bus 消息驱动微服务:Spring Cloud Stream 分布式服务跟踪:Spring Cloud Sleuth 工程使用版本 <dependency> <groupId>org.
el-tree-transfer
简介·请先阅读文档及版本说明
el-tree-fransfer是一个基于VUE和element-ui的树形穿梭框组件,使用前请确认已经引入元素-ui!此组件功能类似于element-ui的转移组件,但是里面的数据是树形结构!实际上,el-tree-transfer依赖的element-ui组件分别是Checkbox多选框,Button按钮,和最主要的Tree树形控件写成!并非是在element-ui的穿梭框组件上的扩展,而仅仅是参照了其外观样式和功能。
因为公司业务使用VUE框架,UI库使用的元素的用户界面。在市面上找到一个好用的VUE树形穿梭框组件都很难,又不想仅仅因为一个穿梭框在元件的UI之外引入其他重量级插件,因此就有了EL-树转移。轻量,易用,无需投入其他学习成本。
[在线访问](http://tree-transfer.zhongxiang.shop/) - [GitHub](https://github.com/hql7/tree-transfer) - [NPM](https://www.npmjs.com/package/el-tree-transfer) - [SegmentFault](https://segmentfault.com/a/1190000015553081) - [CSDN](https://blog.csdn.net/qq_15390381/article/details/80943549)- [掘金](https://juejin.im/post/5b3ecae8e51d4519213fae4b)
注意! 1.9.0 版本增强id为数字型的匹配强度,1.9.7版本增加`defaultTransfer`属性用来满足用户不想将数据拆分成fromData和toData的需求
注意! 1.8.9 版本修复一个节点既是一侧的枝干节点又是另一侧的叶子节点时穿梭引起的重复错误!解决自定义节点名时筛选无效错误。
注意! 1.8.7 版本增加通讯录模式,可通过 mode 字段配置模式
注意! 1.7.7 版本移动事件参数调整,直接返回移动后的 fromData 数据和 toData 数据。
注意! 1.5 以上版本改为自动处理
这里有一个兄弟组件-树形表格:[在线访问](http://eltreetable.zhongxiang.shop/) - [GitHub](https://github.com/hql7/el-tree-table)
第一层数据的pid请设定为0!
id推荐为字符串,但也可以是数字,请不要混用,id不能重复!
快速上手
先NPM下载插件
npm install el-tree-transfer --save
或
npm i el-tree-transfer -S
然后你可以像使用普通组件一样使用el-tree-transfer
<template>
<div>
// 你的代码
...
// 使用树形穿梭框组件 <tree-transfer :title="title" :from_data='fromData' :to_data='toData' :defaultProps="{label:'label'}" @addBtn='add' @removeBtn='remove' :mode='mode' height='540px' filter openAll>
1 引言 最近在开发一个应用软件,为方便调试和后期维护,在代码中添加了日志,用的是Python内置的logging模块,看了许多博主的博文,颇有所得。不得不说,有许多博主大牛总结得确实很好。似乎我再写关于logging的博文有些多余,但不写总结又总觉得没掌握。那就写写吧,也方便日后回顾。 开始总结之前,先感谢几位博主,他们的博客写得很是详尽: 云游道士的博文: https://www.cnblogs.com/yyds/p/6901864.html Nicholas的博文: https://www.cnblogs.com/Nicholas0707/p/9021672.html 说说为什么需要添加日志? 就像上面说的,为了调试和后期维护方便。也许在开发中没有太大体会,但是如果将软件部署到了生产环境中,一旦出现bug,没有日志,就很难对当时的情况进行追踪,有了日志,就可以根据日志尽可能的对当时的数据环境进行还原,方便debug。甚至,只要日志设计得足够合理,还可以用于后续业务数据分析等。 2 日志等级 为什么需要对日志进行划分等级呢? 当我们出于开发时debug的目的使用日志时,我们自然是想尽可能详尽得记录日志,但是如果部署到生产环境中,这样做就可能因为大量的IO占用服务器资源,所以在生产环境中就只需要记录异常信息、错误情况等就好了。 所以,给日志设置等级,可以方便得、因地制宜控制日志输出。 这里只介绍Python的logging模块的日志等级(当然,其他日志系统的日志等级划分事实上也基本相同)。logging的日志等级包括5个: 日志等级(level) 描述 DEBUG 最详细的日志信息,典型应用场景是 问题诊断 INFO 信息详细程度仅次于DEBUG,通常只记录关键节点信息,用于确认一切都是按照我们预期的那样进行工作 WARNING 当某些不期望的事情发生时记录的信息(如,磁盘可用空间较低),但是此时应用程序还是正常运行的 ERROR 由于一个更严重的问题导致某些功能不能正常运行时记录的信息 CRITICAL 当发生严重错误,导致应用程序不能继续运行时记录的信息 日志等级从上到下依次提高,当在程序中设定某个日志等级之后,比设定的日志等级低的日志记录将会被忽略,即logging就只会输出大于和等于设定的等级的日志。我们将在下文中通过代码示例证明这一点。 3 记录日志 logging模块提供两种方法记录日志: (1)通过logging模块提供的模块级函数记录日志; (2)通过logging模块提供的4大组件记录日志。 3.1 记录日志之logging模块级函数 在logging模块中,分别给出一个模块级别函数与上面说到的日志级别相对应,用于输出对应级别日志记录: 函数 说明 logging.debug(msg, *args, **kwargs) 创建一条严重级别为DEBUG的日志记录 logging.info(msg, *args, **kwargs) 创建一条严重级别为INFO的日志记录 logging.warning(msg, *args, **kwargs) 创建一条严重级别为WARNING的日志记录 logging.error(msg, *args, **kwargs) 创建一条严重级别为ERROR的日志记录 logging.critical(msg, *args, **kwargs) 创建一条严重级别为CRITICAL的日志记录 也有一个函数汇总了上面5个函数的功能: 函数 说明 logging.log(level, *args, **kwargs) 创建一条严重级别为level的日志记录 现在可以来尝试使用一下上面的函数了: import logging logging.
提高复用性加static就可以在类里直接调用该方法static 静态修饰符 描述的方法可以直接调用 为什么要有方法? 方法(又叫函数)就是一段特定功能的代码块。方法提高程序的复用性和可读性。 比如,有了方法,我们可以把要重复使用的一段代码提炼出来,然后在每个需要执行这段代码的地方去调用即可。 在一个打飞机的游戏中,飞机需要发射子弹,那么我们可以把发射子弹的这段代码写成方法,这样就可以避免每次重写相同的代码。 方法的格式 语法: 访问权限修饰符 [其他的修饰符 如static] 返回值类型 方法名(参数类型1 形参1,参数类型2 形参2,...){ //形参列表 //方法体 return 返回值; } 方法的格式说明: 修饰符:目前就用 public static。后面我们再详细的讲解其他的修饰符。 返回值类型:就是功能结果的数据类型。 方法名:见名知意,首字母小写,遵守驼峰命名法。方便我们的调用。 参数: 实际参数:就是实际参与运算的。 形式参数;就是方法定义上的,用于接收实际参数的。 参数类型:就是参数的数据类型 参数名:就是变量名 方法体语句:就是完成功能的代码。 注意: 1、若当前方法中不要使用形参,那么形参列表中可以为空 2、实参和形参的类型要相互兼容,且:实参的取值范围要小于或者等于形参类型的取值范围。 在调用方法中,如果我们定义的方法有参数,就必须在调用方法的同时传入这个值,即给当前方法中的参数赋值,而这个传入的值我们称为实际参数,也就是实参 实参:传入的参数值 形参:接收实参传过来的值。 注意:实参名与形参名可以相同,也可以不同。 小结:形参就是一个变量,实参就是一个值,传参就是把一个值给一个形参赋值 小结:形参就是一个变量,实参就是一个值,传参就是把一个值给一个形参赋值
MDK5软件入门 这里主要记录一下MDK5软件的介绍及使用。
MDK5简介 MDK 源自德国的 KEIL 公司,是 RealView MDK 的简称。在全球 MDK 被超过 10 万的嵌入式开发工程师使用。目前最新版本为:MDK5.14,该版本使用 uVision5 IDE 集成开发环境,是目前针对 ARM 处理器,尤其是 Cortex M 内核处理器的最佳开发工具 新建MDK5工程 在完成安装MDK5软件后,打开软件,点击Project->New uVision Project,如图所示:
弹出新建工程界面:
这里选择工程创建的目录位置,编辑工程名,(例如:test)新建文件夹USER,保存在这里。之后会弹出选择器件的对话框,根据STM32型号选择对应的型号就可以了,这里我根据我的STM32F103ZET6型号选择。
特别主要,一定要安装对于的器件pack才会显示这些内容,如果没得选择,先关闭MDK,下载对应的pack安装后再打开创建工程
点击OK后会弹出运行环境选择对话框。
这个是MDK5新增的一个功能,在这里我们可以添加自己需要的组件,从而方便构建开发环境,不需要的话直接点击Cancel即可。
工程初步建立如下:
这里就完成新建一个MDK5的工程了。
新建STM32开发环境 通过上面的操作已经新建了一个框架了。但还不够,还需要添加启动代码,以及.c文件等等。
启动代码是一段和硬件相关的汇编代码,必不可少,主要作用如下:
堆栈的初始化;初始化程序计数器(PC);设置向量表异常事件的入口地址;调用main函数。
这里意法半导体(ST)公司提供了3个启动文件给我们,分别对应不同容量的STM32芯片。我们目前使用的基本都是大容量产品,所以选择startup_stm32f10x_hd.s作为我们的启动文件。
我们找到Target1->Source Group1->双击->设置打开文件类型为Asm Sourcefile->选择startup_stm32f10x_hd.s->点击Add,如图所示:
现在就可以开始编写自己的代码了,但是现在的目录结构还是有点混乱,也就是工程下乱七八糟什么都有。
我们需要进行整理一下。
接下来,我们在 Project 工程目录下面, 新建 3 个文件夹 CORE, OBJ 以及STM32F10x_FWLib。CORE 用来存放核心文件和启动文件,OBJ 是用来存放编译过程文件以及 hex 文件STM32F10x_FWLib 文件夹顾名思义用来存放 ST 官方提供的库函数源码文件。已有的 USER 目录除了用来放工程文件外,还用来存放主函数文件 main.c,以及其他包括 system_stm32f10x.c 等等。
下面我们要将官方的固件库包里的源码文件复制到我们的工程目录文件夹下面。打开官方固件库包,定位到我们之前准备好的固件库包的目录下面,将目录下面的 src,inc 文件夹 copy 到我们刚才建立的 STM32F10x_FWLib 文件夹下面。src 存放的是固件库的.
出现如下错误: 上面的第一,第二,第三个错误的原因是:没有加函数返回值类型void
最后一个原因是:关键字static错误。
总之,出现标识符错误,就是说程序里的不是缺少标识符,就是标识符拼写错误。
由于在proxmox中运行openfiler作为ISCSI虚拟设备系统,因此要为openfiler挂载物理硬盘.新加硬盘在proxmox中认定为/dev/sdb.(注:sdc为存储镜像文件的硬盘)
然后进入ssh,在shell中输入
#qm set 100 --sata1 /dev/sdb,
root@proxmox1:/etc# qm set 100 --sata1 /dev/sdb
update VM 100: -sata1 /dev/sdb
此时可以在openfiler虚拟机中的硬件中看到硬盘sata1.
data1在图形介面下不能添加
如下方法挂载更合理:
添加物理磁盘到虚拟机中
需要在shell下通过CLI的方式来添加,
使用的工具为qm(Qemu/KVM虚拟机管理器),
通过命令”set“来设置物理磁盘到虚拟机中。
qm set <vm_id> --<disk_type>[n] /dev/disk/by-id/- b r a n d − brand- brand−model_ s e r i a l n u m b e r v m i d : 之 前 创 建 虚 拟 机 时 指 定 的 。 < d i s k t y p e > [ n ] : 磁 盘 的 总 线 类 型 及 其 编 号 , 总 线 类 型 可 以 选 择 I D E 、 S A T A 、 V i r t I O B l o c k 和 S C S I 类 型 , 编 号 从 0 开 始 , 最 大 值 根 据 总 线 接 口 类 型 有 所 不 同 , I D E 为 3 , S A T A 为 5 , V i r T I O B l o c k 为 15 , S C S I 为 13 。 ” / d e v / d i s k / b y − i d / < t y p e > − serial_number vm_id : 之前创建虚拟机时指定的。 <disk_type>[n] : 磁盘的总线类型及其编号,总线类型可以选择IDE、SATA、VirtIO Block和SCSI类型,编号从0开始,最大值根据总线接口类型有所不同,IDE为3,SATA为5,VirTIO Block为15,SCSI为13。 ”/dev/disk/by-id/<type>- serialnumbervmid:之前创建虚拟机时指定的。<disktype>[n]:磁盘的总线类型及其编号,总线类型可以选择IDE、SATA、VirtIOBlock和SCSI类型,编号从0开始,最大值根据总线接口类型有所不同,IDE为3,SATA为5,VirTIOBlock为15,SCSI为13。”/dev/disk/by−id/<type>−brand-KaTeX parse error: Expected group after '_' at position 6: model_̲serial_number” : 为磁盘ID的具体路径和名称。
使用面向对象的思想写有限状态机 好久好久没更新了,现在俺又回来了嘻嘻。
——————————————————————分割线————————————————————————————
今天要讲的呢,是通过使用面向对象的思想,写一个简单的有限状态机。说起面向对象,相信大多数人都不陌生,虽然在一开始学这种思想的时候会有点难,而且因为抽象思维很重,所以一开始也不太敢去真的使用这种思想,但是我觉得,其实只要慢慢多去写代码,多去理解使用类,接口等的意义,后面学起来还是可以很容易上手的,而且会有一种,万物皆可面向对象的感觉。
至于什么是对象这种有点哲学的问题我就不回答了,但是有一点,就是时刻要问自己什么是“类”,什么是“接口”。我记得我曾经在一次实习的时候,他们的技术总监问了我一个问题——什么是类??然后我回答了一个——Class呗。反正现在想起来怪怪的,因为之前对面向对象这种思想不是很通透,学的不够深入,能有这种回答也是正常。但是在C#等一些编程语言中,类的确就是class。
在这里的话,我觉得可以这样理解,类就是一些具有相同性质的事务的总称。比如在我们开发游戏的时候,为角色写攻击的代码,角色可能有不同的技能或者说攻击方式,但是这些技能和攻击方式都是会造成伤害或者是会消耗魔法值,这就是他们的一些共性,然后我们可能就会写攻击类,或者是技能类,要用的时候只要调用或者继承。
好了,废话不多说,我们开始进行我们的有限状态机的开发吧。这里的有限状态机我们可以引用unity维基百科的一个案例来进行操作和学习。原地址:unity有限状态机
首先打开unity,新建两个脚本,一个取名为FSMState,一个取名为FSMSystem,然后打开两个脚本。
好,建好了两个脚本,先问一个问题:什么是有限状态机???
————————————————————10秒钟冥想————————————————————————————
冥想结束。有限状态机,顾名思义,就是拥有有限个状态的机器,FSM的全称是Finite State Machine。那么根据有限状态机的意思,我们便可以推测出,状态个数永远会大于等于1个,且小于n。而且所有状态都是某个事物身上发生的,状态之间都是有类似的共性。于此,我们便有FSMstate这个类文件,它主要是所有状态的一个抽象化,并不是具体的状态,**但它有状态需要的方法或者条件。**而FSMSystem则是管理所有状态的一个管理器,也就是状态管理器系统。理解了这两个的意义,对写代码会有很大的帮助。
————————————————————分割线————————————————————————————————
现在呢,我们通过为一个NPC怪物写巡逻状态机让它动起来。在unity商店下载一个怪物的资源包:Dragon the Terror Bringer and Dragon Boar,然后导入,选择到一个做好的龙的预制体,把动画组件去掉,改名为NpcDragon,然后调整摄像机位置,这个龙就是我们要为它写状态的对象。
场景布置好了,我们再回到它的一个动画目录里,看一下它有哪些动画
好像动画还挺多的,不过没事,我们先画一个简单的图:
根据上面的图,其实我们发现,主要的三种状态无非是攻击,移动,静止,然后再添加其他的一些别的状态。但是这些状态之间的转换是有条件的,比如攻击状态,必须要在攻击范围之内且主角是活着的才能攻击。根据这样的一种构思,我们开始写FSMState的脚本:
using System.Collections; using System.Collections.Generic; using UnityEngine; /// <summary> /// 状态类 /// </summary> public enum Transition//状态所对应的一个转换条件,也可以理解为判断是否可以进入该状态的一个条件 { NullTransition=0, LostPlayer,//失去玩家目标,继续巡逻 Rest,//进行休息,对应静止待命 Getplayer,//发现目标,进入攻击状态 } public enum StateID//四个主要状态的ID,我在这里进行了简化处理 { NullStateID=0, Patrol,//巡逻 Idle,//静止状态 Attack,//处于攻击状态,即发现了目标准备进行攻击 } public abstract class FSMState//抽象类 { protected FSMSystem fsm;//定义一个状态管理器 //定义一个字典,用来保存状态对应的条件和状态本身 protected Dictionary<Transition, StateID> map = new Dictionary<Transition, StateID>(); //封装状态ID protected StateID stateID; public StateID ID { get { return stateID; } } public FSMState(FSMSystem fsm)//构造函数初始化,绑定状态管理器 { this.
我们在VB中保存工程时会自动生成很多文件,其中最常见的文件后缀名有 vbp、vbw 和 frm,各位小伙伴有没有好奇他们都是什么意思呢?今天小编给大家发送福利啦,给大家分别介绍一下这些神奇的扩展名!
一、基本扩展名 首先我们vb中一个工程必须包含的文件类型是vbp vbw 和 frm .vbp 跟踪所有部件的工程文件,是关键的文件,它用来保存当前工程中的工程版本、版权及窗体的信息。
.vbw 保存了你最后保存工程时候的情况,比如打开了什么窗口,你编辑到了第几行等。以便下次打开能很容易找到上次的感觉.
.frm 是每个窗体都有的,保存窗体的代码,你可以用记事本打开;
.frx 每个窗体的二进制数据文件,它含有窗体上控件的属性数据。保存一个工程时他会自动生成.vbp 和.vbw 这两个文件但frx是不一定有的,如果窗体中没有出现使用二进制的属性那么就不会出现frx文件。对含有二进制属性(例如图片或图标)的任何 .frm 文件都是不可编辑的,这些文件都是自动产生的。
.cls 每个类模块的一个文件
.bas 每个标准模块的一个文件
.ocx 一个或多个包含 ActiveX 控件的文件
.res 单个资源文件,该文件是可选项。
.SCC MSSCCPRJ.SCC是Visual SourceSafe的配置。用于团体开发,一般没用。 如果你是单机个人工作,可以删。工程文件格式Microsoft Visual Basic 在设计和运行时都利用和创建一些文件。工程或应用程序需要哪些文件取决于它的范围和功能。
二、Visual Basic 在创建和编译工程时要产生许多文件 这些文件分类如下:设计时文件、杂项开发文件和运行时文件
(一) 1.设计时文件
设计时文件是工程的建造块:例如基本模块 (.bas) 和窗体模块 (.frm)。
2.杂项文件
杂项文件是由 Visual Basic 开发环境中的各种不同的进程和函数产生的:例如打包和展开向导从属文件 (.dep)。
3.运行时文件
编译应用程序时,所有必须的设计时文件都被包括在运行时可执行文件中.
(二) 1-设计时和杂项文件的常见扩展名描述:
.bas 基本模块
.cls 类模块
.ctl 用户控件文件
.ctx 用户控件的二进制文件
.dca 活动的设计器的高速缓存
.ddf 打包和展开向导 CAB 信息文件
【题目描述】
尼克爷爷的岁数、爸爸的岁数和他自己的岁数是3个等差的自然数,每两个数相差25.已知尼克为a岁,那么请输出他们的岁数。
【输入】
一个整数,表示尼克的岁数
【输出】
输出一行,包含三个数,分别表示尼克的岁数、尼克爸爸的岁数、尼克爷爷的岁数,数与数之间以一个空格分开
【输入样例】
9
【输出样例】
9 34 59
代码
#include<cstdio> using namespace std; int main() { int a,b,c; scanf("%d",&a); //输入尼克的岁数 b=a+25; //计算尼克爸爸的岁数 c=b+25; printf("%d %d %d",a,b,c); //输出三人的岁数,中间用空格隔开 return 0; } 代码
#include<iostream> #include<cstdio> using namespace std; int main() { int a,b,c; cin>>a; b=a+25; c=b+25; printf("%d %d %d",a,b,c); return 0; }
文件IO 1、文件,
一般指存储在外部介质上数据的集合。一批数据是以文件的形式存放在外部介质(如:磁盘,光盘和U盘上)。操作系统是以文件为单位对数据进行处理的。若想找存在于外部介质上的数据,必须先按文件名找到指定的文件,然后再从文件中读取数据。在外部介质上存储信息,也是需要先建立一个文件,才能向他输出数据。
2、对用户来说,常用的文件有两大类,一类是程序文件,(C++的源程序文件.cpp,目标文件.obj,可执行文件.exe), 另一类是数据文件(data file)
程序运行时,常需要将一些数据(运行的最终结果和中间数据)输出到磁盘上存放起来,必要时再从磁盘输入内存。这种磁盘文件就是数据。程序中输入输出的对象就是数据文件。
3、文件中数据的组织形式可以分为 ASCII 文件和二进制文件。ASCII文件又称为文本文件(text)或 字符文件,它的每一个字节放一个ASCII代码,代表一个字符。二进制文件又称内部格式文件或字节文件,是把内存中的数据按内存中的存储形式原样输出到磁盘上存放。
4、对于字符信息,在内存中是以ASCII码形式存放的,因此,无论使用ASCII码形式输出和用二进制文件输出,其数据形式都是一样的。对数值信息就不一样。?
5、用ASCII码形式,输出的数据与字符一一对应,一个字节代表一个字符。可直接阅读,占的存储空间较多,花费转换时间(二进制形式与ASCII码)。
使用内部格式(二进制形式输出)输出数值,可节省外存空间,不需转换时间,但不可直接显示内容。
一般,程序运行中有些中间数据暂时保存在磁盘文件中,之后又需要输入到内存的,用二进制合适。为了显示内容或打印以供阅读,应选择ASCII形式输出。(低级IO -> 高级IO)
6、文件流
#include <fstream> ofstream f1; 建立一个输出文件流对象 f1.open(磁盘文件名,输入输出方式) open一般调用形式,文件名可为路径,缺省默认当前目录 文件的输入输出方式设置值 ios:: 设置值 in out app ate trunc binary ios::in | ios::out ios::in | ios::binary ios::out | ios::binary 输入,
输出,已有重名文件,清空
输出,添加在末尾
打开已有文件,文件指针指向末尾
打开一个文件,若文件存在,删除全部数据。不存在则建立新文件。如已制定out而为制定 app ate in,则同时默认此形式。
默认二进制打开,不指定此形式,默认ASCII码
输入加输出
二进制打开输出文件
二进制打开输入文件
打开失败时,open函数返回 0 如果是调用构造函数的形式打开文件,则流对象的值为 0
关闭磁盘文件,
f1.close(); 后面的内容就没仔细看了,后面还是要看。做了模拟题库,结果后面还是考了一些细碎的点。
7、对ASCII文件操作
ASCII码文件:每一个字节都以ASCII码形式,存放数据,一个字节存放一个字符。
系统函数 exit() 参数为1,0,或任意整数,结束运行。旧版本需头文件 <stdlib.h>
8、对二进制文件操作
突然有更改proxmox的IP地址的需要,既然是debian的底子,那就好办,更改/etc/network/interfaces中的virtnet0的IP即可。重启。搞定。慢着!重启后的提示语还是原来的https://旧IP:8006。不行!这个要是以后忘了不就给自己挖了个大坑了?更改/etc/issue,没错就是它,重启,什么?不起作用。系统自动改为原来的IP。这肯定是系统自动生成的啦!在哪个脚本中呢?先不管,也不好查,一定是根据系统设置生成的,目光定在了/etc/hosts文件,原来这里边的内容没变,还是原有旧IP。改掉重启,完美搞定!
解释一下:实际起作的的是第一步:更改/etc/network/interfaces中的virtnet0的IP即可
后面两步是为以后的维护而改的,想想以后忘了改IP这事,按旧的提示访问会以为ip不通!!
参考这个,但是它讲的有的也是多余的操作,参考即可,实测可以解决问题
http://tieba.baidu.com/p/5833424006?traceid=
多任务多线程 多任务"并行处理" 首先我们来理解一下并行处理,初学者写程序通常是顺序执行,当我们逐渐想成为“专业”人士的时候顺序执行 的程序已经不能满足我们了,所以就需要多任务多线程系统,市面上标准的一些操作系统比如ucos,freeRTOS这些操作系统需要的学习周期长,范围广。在网上看到了一本书"单片机编程魔法师之高级裸编思想"在没学会ucos的阶段学习用这种思想过度感觉非常nice!
单片机是支持多任务同时并行地运行在一个系统中,在具体介绍之前先看一看单片机的硬件结构
这个图中我们可以看出,单片机的运行是在ALU的主导下进行的;而定时器指是一个定时装置,它在定时计数期间是无需ALU干预的,完全独立运行;串口的通讯单元对数据的接收与发送也是完全独立完成的,并不需要ALU干预。很显然这三个任务是并行处理,切互不干涉,只有在定时器或串口产生中断时才会到代码中临时运行一段程序,已向单片机的主体运行过程交付一下结果,以便进行汇总处理。
微操作系统 简单一点来说就是一个while(1)但是while中我们采用多任务多线程的方式管理。首先我们要知道任务有生死,生死是一个过程所以具有寿命。
一个任务的线程:假设一个任务的执行代码有50步,通常编程只会一次执行完毕,但是我们现在需要想想,因为我们会嫌这个任务总占用着ALU的时间而影响其他任务的执行效果,所以就可以对任务进行划分,把它分为5份,每份10步,这样我们每次执行其中的一个程序片–每次正在运行的程序片我们称为线程。
这个图很完美的解释了线程的运行原理。
具体线程的实现:
typedef struct{ u8 isTask_Living; u8 Thread_Process; }myTask; void Task(void) { if(Task.isTask_Living) { Task.isTask_Living = !myThread3(&Task3,&Task3.Thread_Process); } } /*初始化任务变量*/ void InitTask4(myTask4 *Task) { Task->isTask_Living=1; Task->Thread_Process=0; } /*功能:任务线程 **参数:myTask:Task任务类型 ** :Process:unsigned char*类型,线程指针 **返回值:CHAR类型,线程结束,或未结束 */ static int myThread(myTask *Task,unsigned char *Process) { int ret=0; switch(*Process) { case 0: //程序片1 break; case 1: //程序片2 break; case 2: //程序编3 break; default:break; } (*Process)++; if(*Process>3) { ret = -1; *Process = 0; } return ret; } void TaskCommunication(void) { if(Task.
记录一下使用java SE 过程中,为了避免使用code硬编码某些参数,使用基础读取配置文件的方式获取数据
工具类代码如下
public class PropertyUtil { //项目配置文件路径前缀 private static String CONFIG_FILE_PATH_PREFIX = PropertyUtil.class.getClassLoader().getResource("").getPath().substring(1); private static String CONFIG_FILE_PATH = null; private static Properties properties = new Properties(); /** * <简要描述>: <Br/> * @param configPath 配置文件在src下的路径。例如config/db.properties * @param key 配置项 * @return * @return String 返回具体的配置内容 */ public static String getSpecificProperties(String configPath,String key){ String value = null; try { properties.load(new FileInputStream(CONFIG_FILE_PATH_PREFIX+configPath)); value = properties.getProperty(key); } catch (IOException e) { // TODO Auto-generated catch block e.
Linux用户与用户组配置文件详解 出发点
Linux是一个多用户多任务的操作系统,用户需要使用系统,就必须在系统中拥有属于自己的账号。
作为一个Linux管理员,对用户增删改查等操作当然离不开用户与用户组的配置文件了,熟练的掌握与运用用户与用户组的配置文件是必不可少的学习一步,接下来我会详细介绍用户与用户组的配置文件。
1、与用户有关的配置文件(/etc/passwd),所有用户权限为可读 Linux基本思想之一:一切都是文件
passwd:存放用户账户及其相关信息(密码除外)
vim打开passwd用户配置文件
passwd文件中包含了系统所有用户的基本信息,一行定义一个用户账户,每行均由7个不同的字段构成,各字段用“:”分割
第一个字段(第一个root):用户名
第二个字段(x):加密的密码(为了安全去,使用“x”占位代表)
第三个字段(第一个0):用户ID
第四个字段(第二个0):用户组ID
第五个字段(第二个root):用户的描述信息(默认用户的全名或空值)
第六个字段(/root):用户的主目录
第七个字段(/bin/bash):登录shell(字段为/sbin/nologin,表示禁止登录)
用户名:加密的密码:UID:GID:用户名全名或描述信息:用户主目录:登录shell
如果要禁用某个用户账户,可以修改/etc/passwd文件,在该用户对应的行首添加“#”符号(linux中行首第一个字符为#,代表这一行为注释),或者用户的shell设置为/sbin/nologin
2、用户账户密码信息配置文件(/etc/shadow),只有超级用户root可读,普通用户无法读取 shadow文件中,每个用户信息也是占用一行,由9个字段组成,中间用冒号“:”分割
vim打开shadow配置文件
从左往右依次是:
第一个字段(root):用户名
第二个字段($…0):加密后的密码(如果为空,用户不需要输入密码即可登录)
第三个字段(空值):密码的最后一次修改时间(这是一个相对时间,即从1970年1月1日到修改时的天数)
第四个字段(0):密码在多少天内不能更改
第五个字段(99999):密码在多少天后必须更改
第六个字段(7):密码到期前多少天给用户发出警告
第七个字段(空值):密码在多少天后用户账户将被禁用
第八个字段(空值):密码被禁用的具体日期(这是一个相对时间,即从1970年1月1日到禁止时的天数)
第九个字段(空值):保留字段
通过vim打开/etc/shadow文件,通过修改相关内容可以达到管理用户的目的
3、设置用户属性的配置文件(/etc/login.defs) 建立用户账户是会根据/etc/login.defs文件的配置信息设置用户的某些属性
vim打开login.defs
MAIL_DIR /var/spool/mail (用户邮箱所在的目录)
PASS_MAX_DAYS 99999 (账户密码最长有效天数)
PASS_MIN_DAYS 0 (账户密码最短有效天数)
PASS_MIN_LEN 5 (账户密码的最小长度)
PASS_WARN_AGE 7 (账户密码过期前,提前警告的天数)
UID_MIN 1000 (使用useradd命令添加账户是自动产生UID,最小UID值)
UID_MAX 60000 (使用useradd命令添加账户是自动产生UID,最大UID值)
SYS_UID_MIN 201 (使用useradd -r 添加账户时自动产生的系统UID,最小UID值)
SYS_UID_MAX 999 使用useradd -r 添加账户时自动产生的系统UID,最大UID值)
GID_MIN 1000 (使用groupadd命令添加账户组时自动产生GID,最小GID值)
关于C语言如何有效正确的学习,我写了一个专栏:你可以这样学习C语言,有兴趣的小伙伴可以来看看哦,希望能对你有收获!本文例子需要源码的可以关注我后私信我。
这几天我用C语言自己写了一个交互小程序。这个交互小程序,我精力主要是在友好性方面,美观方面,我实在没啥天赋。
文末会给大家推荐几本书,希望对需要的朋友有帮助。
这个交互小程序其实很简单,现在很多C语言实例项目,像什么学生管理系统、图书管理系统、通讯录等等”XXX管理系统“,大部分都可以套用这个交互小程序。
先给这个程序上个图吧,程序刚开始运行,首先是一个欢迎界面,如下:
这是一个非常简陋的,欢迎界面。
按照提示,用户按下“ENTER”键,就可以进入到菜单选择界面,界面如下:
按照菜单选择界面的提示,输入数字键0退出整个程序,输入数字键1,进入对应的功能模块function1,输入数字键2,进入对应的功能模块function2。比如,我输入数字键1,进入功能模块function1,如下图:
界面嘛就这样了,美观上来说很简单,很丑陋。不过在友好性方面,背后的逻辑可不像UI看起来这么简单,本文就来分析这背后的逻辑。
一、程序一览 1. 程序代码预览 这个小项目的代码文件不多,截图如下:
每个文件里的代码也不多,很简单,每个文件的用处大概介绍如下:
1)main.c 这个是入口函数文件,用于显示欢迎界面、菜单选择界面,并响应处理用户的输入,调起对应的功能模块;
2)Common.h 这里声明了一些公共函数,比如欢迎界面函数、菜单选择界面函数、提示函数等。这些都需要在main.c中用到。如果功能模块函数要使用一些公共的函数与变量,也可以在这个文件中声明。
3)Common.c 这里是Common.h文件里函数与变量的实现。
4)function.h与function.c 这是功能模块文件。每一个功能模块都有自己的头文件和实现文件。
2. 逻辑结构 整个程序的逻辑结构也很简单,我画了一个示意图,如下:
我在图中也指出了,在这个交互程序上可以很方便地添加功能模块。最后,我会用一个示例来说明如何扩展这个程序。
二、技术点 技术点1. 程序暂停 我在程序中,在几个地方使用
system("pause"); 来设置暂停点。
1) 在显示完欢迎界面后使用一次。当欢迎界面显示后,让用户能够看到欢迎信息,再由用户选择是否消失欢迎界面进入菜单选择界面;
2) 在switch语句中的每个case部分使用了一次。当每次运行完一个功能模块时,应该使得程序运行暂停,让用户看看功能模块的运行结果,再由用户按下Enter键返回菜单选择界面;
3) 在用户结束整个程序时使用了一次,让用户看到程序结束界面,再由用户按下Enter键结束程序。
上述设置这些暂停点纯粹是从用户体验出发的,同时也增强了与用户的交互性。
技术点2. 清屏 我在程序中,有几个地方使用
system("cls"); 来清屏。
1) 在显示完欢迎界面后使用了一次,目的是用户想进入菜单选择界面了,那么就使得欢迎界面消失,为菜单选择界面腾出显示空间。当然,如果你觉得欢迎界面和菜单选择界面在一起显示更好看,你可以去掉清屏。
2) 在switch语句的每个case部分使用了一次。当一个功能模块运行结束后,应该清屏,腾出显示空间给下一个功能模块。因为下一个功能模块有可能有大量的信息需要显示,你上一个功能模块的输出就不要凑热闹了。
待续!
微信公众号:R语言数据分析与实践
1 n阶张量 Tensor张量,在数学中实际上是高维数组,
0阶张量:标量 是一个独立的数字;
1阶张量:向量,
2阶张量:矩阵,
3阶张量:数组,
n阶张量的定义如下表格:
张量 张量案例 2 张量应用 时间序列:3阶向量 尽管有时候时间序列数据看起来像是2阶张量,当你将这些数据的特征以时间为横截面观测时,它们就是3阶张量(包括特征、样本)。
3阶张量 图片数据:4阶张量 单张图片可以看作3阶张量(RGB、高度、宽度),加上样本数,则为4阶张量。
4阶张量
公司里工作,有一些linux服务器主要存放项目分支的代码和一些文档,我们在windows上通过目录映射,可以用notepad、sublime、vs等编辑打开服务器端的文件,这样直接编辑访问服务器的目录显得比较方面,编写代码也可以使用自己习惯的工具。在家里为了在电脑上能连接虚拟机的centos操作目录,通过搭建Samba来实现。
Samba是linux的一个服务。下面介绍一下实现映射的配置过程,注意linux目录的权限,好几次配置完成后,windows访问映射的目录不能进行读写操作,提示无权限。
搭建步骤: 一、安装Samba
没有安装Samba的先进行安装,centos下命令如下
[root@localhost home]# yum install samba samba-client 二、创建Samba账号
首先为samba服务器创建一个用户组:groupadd admin (这里我的用户组和用户都命名为admin,包括后面的密码)
然后,在samba用户组下创建用户: useradd -g admin admin
[root@localhost /]# groupadd admin [root@localhost /]# useradd -g admin admin 接着,给需要映射的目录授权。假设需要映射的目录为/home
# 755可能导致权限不足 [root@localhost home]# chmod -R 777 /home [root@localhost home]# chown -R admin:admin /home 【注意】关于chown命令的使用:先用户其次才是用户组(用户:用户组)
三、修改Samba配置文件
没有安装vim的,yum install vim进行安装
[root@localhost home]# vim /etc/samba/smb.conf 我的配置如下:
注意security字段值不要改为share,可能导致smb服务起不来
linsirs相当于这个目录映射的别名,自己命名即可。指定之前创建的用户组和用户,path就是你需要映射到windows进行访问的目录,其他字段直接照搬就行。
【备注】看了很多博客有配置其他属性字段的,但至少这里新增的字段是能够实现目录的映射的。
四、为samba用户admin设置密码
[root@localhost samba]# smbpasswd -a admin New SMB password: Retype new SMB password: Added user admin.
基本!是基本!!很基础的!!!
一.集合类型 集合是多个元素的无序组合。
元素之间无序,每个元素唯一。
集合元素不能是可变数据类型。
建立集合类型用{}或者set()
建立空集合类型只能用set().
*基本操作符:
| 并
– 差
& 交
^ 补
(这些应该很好理解啦。)
*常用处理方法:
S.add(x) 若x不在S中则将其增加入S
S.discard(x) 移除S中的x(若没有,不报错)
S.remove(x) 移除S中的x(若没有,产生Key Error异常)
S.clear() 移除S中所有元素
S.pop() 随机返回S的一个元素并更新S(若空则产生异常)
S.copy() 返回集合S的一个副本
len(S) 返回集合S的元素个数
x in S
x not in S 判断x是否存在于S中,返回布尔值
set(x) 将其他类型变量x转变为集合类型
二.序列类型 序列是具有先后关系的一族组元素
序列中的元素类型可以不同。
元素间由序号引导,通过下标访问序列的特定元素。
序列是一个基本类型。
序号:从第一个元素(0)开始标记到最后一位。
*序列处理函数及方法
x in S
x not in S 判断x是否在S中,返回布尔值
S+t 连续两个序列s和t
Sn或nS 将序列复制n次
s[i] 索引,返回s中的第i个元素,i是序列的序号
s[i:j]或s[i:j:k] 切片,返回序列中第i到j并以k为步长的元素序列
x[::-1] 返回值是所有元素的逆序
len(s)
之前做计算光学成像,需要用到图像的相位信息。但是设计到傅里叶变化的实部和虚部的问题的时候,发现教科书上一般来讲,只会介绍一句:
如果f(x,y)是实函数,则它的傅里叶变化就是关于原点共轭对称的:
F(u,v) = F*(-u,-v)
也就是说 傅里叶谱关于原点对称。
但是,当原函数f(x,y)不是实数的时候呢
然后我经过测试:
输入:
原信号实部
原信号虚部
上面两个一维信号 构成 一个 复数的 输入信号。
然后把上面复数信号经过fft得到
实部 和 虚部
再来, 原信号的 实部fft得到的 实部和虚部:
可以看到 是:偶对称的实部 和 奇对称的虚部
再来, 原信号的 虚部 fft 得到的 实部和虚部:
可以看到 是:奇对称的实部 和 偶对称的虚部
最后,原信号的实部的fft得到的实部 + 原信号的虚部的fft得到的实部
可以看到和 原信号直接fft的实部 是一样的
最后,原信号的实部的fft得到的虚部 + 原信号的虚部的fft得到的虚部
可以看到和 原信号直接fft的虚部 是一样的
说明:
傅里叶变换中的对称性:
时域信号的实部对应频谱为偶对称实部和奇对称虚部
时域信号的虚部对应频谱为奇对称实部和偶对称虚部
时域信号包含实部和虚部时,频谱是两者的叠加
够不够清晰?
明白了吧?
你要是还不明白,那...就给我留言吧~
Environment CentOS Linux release 7.5.1804 (Core)root 权限下 Process 获取 Php7.1 官方安装包
wget -c http://cn2.php.net/get/php-7.1.27.tar.gz/from/this/mirror 解压安装包
tar -xzvf mirror 查看配置项
./configure --help 配置项中文解释->
配置项设定
./configure --prefix=/opt/php/php71 --with-fpm-user=www --with-fpm-group=www --with-curl --enable-fpm --enable-inline-optimization --disable-debug --enable-shared --enable-soap --with-xmlrpc --with-openssl --with-mcrypt --with-mhash --enable-bcmath --with-bz2 --enable-calendar --enable-exif --enable-ftp --with-gd --with-jpeg-dir --with-png-dir --with-zlib-dir --with-freetype-dir --enable-gd-native-ttf --with-gettext --enable-mbstring --enable-sockets --with-libxml-dir --with-xsl --enable-zip --with-pear --enable-opcache --enable-pcntl --with-pdo-mysql --enable-sysvmsg --enable-sysvsem --enable-sysvshm 依赖包报错以及处理
error: libxml2 not found. Please check your libxml2 installation.
关于修改WIFI代理后手机部分APP无法使用的解决办法 最近在练习爬虫抓取手机app数据时出现了一个问题,就是修改wifi代理,使用fiddler代理时,使用斗鱼app显示无法连接到服务器,在网上搜索了一下结果,个人觉得可能是网络证书的问题,下面是我自己的解决方法 解决方法 在手机浏览器中输入地址:http://localhost:8888/, 点击FiddlerRoot certificate,下载安全证书:下载完证书后安装该证书。安装完证书后可以在手机设置中的“受信任选项凭据”中看到用户自己保存的安全证书证书安装完毕后,在更改wifi代理为本机代理时,就不会出现无法连接到服务器的问题
MATLAB Filter Designer实际应用 有时候数据看起来很凌乱没有章法,需要滤波,可以在时域也可以在频域,这里介绍一种比较实用的利用MATLAB进行带通滤波(频域)的方法,主要是利用MATLAB工具箱中的信号处理工具箱。
1.找到MATLAB中的Filter Designer 工具箱
2.进入下图
最左边一栏 可以选择低通滤波,高通滤波,带通滤波等滤波方法
这里选择第三个 带通滤波(从频域上进行滤波) 选择FIR和IIR中的FIR
3.第二列 上面 选择minimum order 下面的默认
4.Frequency Specifications
Fs:采样频率,需要符合香农采样定理
Fs>=2Fmax
例子:Fmax为原始数据频率的最大值,频率 f=1/T 如果原始数据的采样周期是 0.06那么频率是 1/0.06
Fs是 (1/0.06) * 2
Fstop 和Fpass 区间是衰减区间,不能正常通过,Fpass1和Fpass2区间是可以通过的,符合频率要求的信号,
比如已知正常的人体脉搏脉为 60~120次/min 那么可以Fpass1和Fpass2为 1HZ到2HZ,Fstop1和Fstop2决定了衰减区间,同时和滤波器的阶次有很大的关系
代表增益(衰减倍数) 在两个不同衰减区间倍数可能不同 这里的dB稍做解释:
20lg X = Y dB X是增益倍数,Y是表示出来的规格 如果填 60dB, 20lg X =60 → X=1000; 那么衰减倍数就是1000;
5.此时已经设计好了滤波器,选择Export 保存到一个位置,注意调用这个滤波器是调用保存时候的系数!!!
有2个名字很关键,一个保存好的.mat文件名字,另一个是 上图中的 Numerator 中的Num就是需要调用的系数
6.如何使用
(1)先从 Work Space中 用load(‘保存的文件名.mat’)导入这个滤波器系数
(2) filtered_Data = filter(Num,[1],Data(:,2));
ceph集群的pg非常重要,同时pg数量,也影响到集群的存储分布,那到底该如何规划pg数呢?
一旦设置pg和pgp数量,就不需要再调整,否则会引发数据的大量迁移。如果一定要调整,请确保调整前,集群是ok状态
pg 跟 pool 关联,一个pool有多少个pg,跟osd数相关
PG和PGP数量一定要根据OSD的数量进行调整,计算公式如下,但是最后算出的结果一定要接近或者等于一个2的指数:
One pool total PGs = (Total_number_of_OSD * 100) / max_replication_count 例如15个OSD,副本数为3的情况下,根据公式计算的结果应该为500,最接近512,所以需要设定该pool(volumes)的pg_num和pgp_num都为512
ceph osd pool set volumes pg_num 512 ceph osd pool set volumes pgp_num 512 https://ceph.com/pgcalc/ 官方指导建议,
不明白vim使用的,可以参考Linux常用命令之文件基本操作(一)vi、vim,这里主要介绍centos不能使用vim的解决方法。
都知道,不能使用,可能还没安装,所以先检查是否安装,通过命令:
rpm -qa |grep vim 1、Web Storage的产生2、Web Storage简单介绍3、Web Storage的问题4、LocalStorage用于存储Jwt Token 一、概述 在Session篇说过为了维持Http请求有状态化,需要有“会话”的概念,服务端信息+客户端信息共同协作维持会话。
其中Cookie是会话在客户端的载体,Session是会话在服务器端的载体。客户端会话存储在浏览器中。服务器端会话存储在Web中间件中。
二、Cookie产生背景 单论Cookie的产生,网上查是早于Session,当时只是想在浏览器端保存一些网站的设置信息,所以起了这么个名字。理论上登录才是第一需要解决的问题。。。
三、Cookie值在哪里设置 Cookie的内容由服务器端产生,通过构建Cookie对象,调用Response的setCookie方法设置。或者直接通过Response的addHeader方法来设置,通过Response Header传递给浏览器端。
Cookie cookie = new Cookie("test", "11"); cookie.setPath("/"); cookie.setHttpOnly(true); response.addCookie(cookie); // response.addHeader("Set-Cookie", "uid=1123456; Path=/; HttpOnly"); Cookie也可以在前台通过js设置,一般用于后台不方便设置的时候,如我们在ajax访问中希望在返回结果后增加Cookie。
document.cookie="name="+value; 四、Cookie有哪些属性 Cookie主要属性是一个键值对name和value,还有其它的附属控制属性。
我们可以查看Java中Cookie的源码
private String name; private String value; private String comment; private String domain; private int maxAge = -1; private String path; private boolean secure; private int version = 0; private boolean isHttpOnly = false; public Cookie(String name, String value) { // 构造函数逻辑 } 属性说明:
Locks
Online migrations, snapshots and backups (vzdump) set a lock to prevent incompatible concurrent actions on the affected VMs. Sometimes you need to remove such a lock manually (e.g., after a power failure).
qm unlock root@proxmox1:/etc/apt# qm
ERROR: no command specified
USAGE: qm [ARGS] [OPTIONS]
qm guest cmd <vmid> <command> qm guest exec-status <vmid> <pid> qm guest passwd <vmid> <username> [OPTIONS] qm guest exec <vmid> [<extra-args>] [OPTIONS] qm clone <vmid> <newid> [OPTIONS] qm config <vmid> [OPTIONS] qm create <vmid> [OPTIONS] qm delsnapshot <vmid> <snapname> [OPTIONS] qm destroy <vmid> [OPTIONS] qm list [OPTIONS] qm listsnapshot <vmid> qm migrate <vmid> <target> [OPTIONS] qm move_disk <vmid> <disk> <storage> [OPTIONS] qm pending <vmid> qm reset <vmid> [OPTIONS] qm resize <vmid> <disk> <size> [OPTIONS] qm resume <vmid> [OPTIONS] qm rollback <vmid> <snapname> qm sendkey <vmid> <key> [OPTIONS] qm set <vmid> [OPTIONS] qm shutdown <vmid> [OPTIONS] qm snapshot <vmid> <snapname> [OPTIONS] qm start <vmid> [OPTIONS] qm stop <vmid> [OPTIONS] qm suspend <vmid> [OPTIONS] qm template <vmid> [OPTIONS] qm unlink <vmid> --idlist <string> [OPTIONS] qm cleanup <vmid> <clean-shutdown> <guest-requested> qm importdisk <vmid> <source> <storage> [OPTIONS] qm importovf <vmid> <manifest> <storage> [OPTIONS] qm monitor <vmid> qm mtunnel qm nbdstop <vmid> qm rescan [OPTIONS] qm showcmd <vmid> [OPTIONS] qm status <vmid> [OPTIONS] qm terminal <vmid> [OPTIONS] qm unlock <vmid> qm vncproxy <vmid> qm wait <vmid> [OPTIONS] qm help [<extra-args>] [OPTIONS] root@proxmox1:/etc/apt#
带了一年15人的技术团队,以下是我对技术团队日常的管理、学习交流会、管理书籍学习,总结出的技术团队管理的建议和看法,希望对大家有所帮助。
1、尊重你的成员,不要觉得自己技术很牛逼,其他人都是傻子,尊重别人的同时,别人也尊重你
2、信任你的成员,给予他们鼓励,帮助他们成长
3、培养你的成员,了解他们的兴趣,帮助规划职业方向,为他们铺路
4、认同你的成员,赞扬他的工作,激励他们成长,指导他们把工作做的更好,给他提出更高的要求
5、技术团队管理不能太技术化,不能只有true or false,要学会变通和交流
6、合理分配团队成员工作,知人善任,人尽其用
7、 提高团队执行力,团队驱动靠的是目标
8、工作安排,不能告诉他们怎么做,而是清楚表达自己的需求,要做的是什么,并委婉的进行确认,培养他们需求理解和动手能力
9、定期的和成员间进行沟通,了解他们的状态和内心对环境的看法
10、任何时候都不能替成员完成工作,要培养他们的责任心和执行力
11、项目进展缓慢,不是人的问题,而是项目管理工作分配的问题
12、对于团队中慢性子的人,不要去约束,而是要锻炼他们自我管理能力
13、不要觉得团队管理就要抛弃技术路线,重复工作可以指导队员去完成,自己多花时间加强平台的优化监控和研究新的一些技术
14、适当加班可以锻炼团队战斗力,抵制无意义的加班,营造高效、愉快的工作环境
15、团队的负责人起着带头作用,上行下效,要规范自己的言行,在约束管理团队成员不好言行时,自己也一定不要去做相同的事情
16、每天自省下自己团队管理中的不足,认可自己的成绩,承认自己的不足并相信自己下次能做好
团队是由基层和管理层人员组成的一个共同体,它合理利用每一个成员的知识和技能协同工作,解决问题,达到共同的目标。
团队的构成要素为目标、人、定位、权限、计划。
团队建设就是通过各种活动,组织团队成员优质高效的完成目标。
团队建设的特点是统一的目标、统一的思想、统一的规则、统一的行动、统一的声音。
统一的目标:先有目标才会有团队。有了团队目标只是团队目标管理的第一步,更重要 的是第二步统一团队的目标,就是要让团队的每个人都认同团队的目标,并为达成目标而努力的工作。
统一的思想:如果团队的思想不统一,你说东他说西,就像人在做思想斗争时会降低行动效率一样,团队思想不统一也会降低效率。
统一的规则:一个团队必须有它的规则,规则是告诉团队成员该做什么,不该做什么。不能做什么是团队行事的底线,如果没有设定底线,大家就会不断的突破底线,一个不断突破行为底线的组织是不能称其为团队的。
统一的行动:一个团队在行动的时候要相互的沟通与协调,让行动统一有序,使整个流程合理的衔接,每个细节都能环环紧扣。
统一的声音: 团队在做出决策后声音一定要相同,不能开会不说,会后乱说,当面一套,背后一套。
高效团队是团队建设的目的与努力方向。高效团队强调了协作、配合、有效的沟通及强有力的执行力。高效团队具有以下特性:
有共同的目标,有约束团队成员朝着这个目标不断努力的机制或制度。
角色定位明晰。各角色职责明确,各岗位不可或缺。
互补的技能。全员参与,注重配合与协调。
共同的工作方法。强调服务,强调实效,强调沟通交流。
工作内容分解(WBS),执行力度,工作检查。
相互依赖并共同承担责任。
领头的作用明显,指引方向,给成员信心,适当激励。
为做好工程项目,在组建团队时,需要作多方面的努力:
首先,项目管理者应做到知人善用,各尽所长。尽可能安排合适的人在合适的岗位,充分发挥出他的优势与特长。
其次,在配合上给力。项目成员必须有团队协作精神,通过协同作战来发挥团队的整体战斗力,即形成合力。从而使整个团队达到最佳状态。古人云:“打虎亲兄弟,上阵父子兵”,强调的就是默契的配合,以及密切的协作。
第三,在工作计划与任务安排上考虑更加全面、到位;如有变动,要及时将变动信息传达到相应的人员,以免造成信息脱节。
团队中存在的问题:
一是人员分工不明确,岗位职责不清晰。项目部成员没有相对明确的分工,岗位职责也不明确,几个人凑在一起,今天你干这个,明天我做那个,没有计划性和考核评价,办事效率低下。
二是执行力差,缺乏积极性和主动性。主要表现:没有养成加班做事的习惯。凡事等着上级安排,推一推,动一动,不推不动。上级不安排工作就坐等,上级不指示就不执行,上级不询问就不汇报,上级不检查就拖着办。很多工作的完成,都是在多次检查、催办下完成的,执行力很差;再就是等待外单位的回复。抱着“我已与你联系过了,静待回音,什么时候回复不是我能决定的,延误工作的责任应该由对方负责,我只能等”这样的心态,不积极、不主动靠前。再就是等待其他部门或其他人的联系。你不找我协助,我就躲避,总有原因可以找,就说情况不清楚。对其他相关工作不关心,没兴趣,多一事不如少一事;等待下级的汇报。任务虽已布置,但是没有检查,没有监督。不主动去深入实际调查研究,掌握第一手资料,只是被动地听下级的汇报,没有核实,然后作决定或向上级汇报,贻误战机,影响效率。
三是缺乏专业知识和工作经验,工作效率不高。比如说**库和尾矿库建设的问题,为如何立项获得批准经历了很多反复,耽误了很多时间,一直是在摸索;黄金文化产业园项目,因为坐标出现偏差,导致重新申报;涌积水与边坡综合治理及防沙绿化生态农业项目,开始是承办公司变更,再加上项目合并,耽误了时间,影响了工作效率;这些问题的出现,其实最根本的问题还是专业能力不足,缺少工作经验。
四是动力不足,工作进展缓慢。团队人员不多,但没有凝聚力,一盘散沙,你干你的,我干我的,缺乏协调和沟通,没有目标和使命感;缺少责任心和监督考评制度。上述现象的出现,主要原因是负责人缺乏责任心和使命感,懒惰,自私造成的,这样的后果就是出现了不学无术、沟通不畅、缺乏责任和担当,履行职责没有痕迹,作而无为等现象。造成的结果就是吃大锅饭,绩效考核指标,动力不足,积极性不高,办事效率低下。
如何搞好团队建设
团队建设,简单讲就是:给你一拨人,你得能把他们拢在一起,朝着一个方向走。
彼得.德鲁克说过:"现代企业不仅是老板和下属的企业,而应该是一个团队。
团队需要建设!
01、强化项目经理的领导力
项目经理既是管理者,又是执行者;既是工作计划的制订者,又是实施计划的领头人,作为团队的"头",其个人素质起着至关重要的作用。要做好这支团队的领头羊,不仅要用平和之心客观公正地对待营业处的每件事和每个人,更重要的是全面提高自身素质。
项目经理在团队管理中相当于搅拌机,通过组织会议、讨论、学习、攻关等活动,与成员之间形成良好的沟通,最终形成明智的决策。项目经理不但要有计划、领导、沟通、交际、应变的能力,还必须具备较强的组织能力。如何将项目成员组织起来,如何发挥他们的工作效率,如何增强团队的凝聚力等,是项目经理必须考虑的问题。
在团队建设中,项目经理要做到以下几点:
一是建立明确共同的目标,项目管理培训,,打造团队精神,抓好目标管理,没有目标,团队就失去了方向。因此,建立一个明确的目标并对目标进行分解,同时通过组织讨论、学习,使每一个单位、每一个人都知道本单位或自己所应承担的责任、应该努力的方向,这是团队形成合力、劲往一处使的前提。
二是抓规范,抓执行,营造积极进取团结向上的工作氛围。衡量一个公司管理是否走上正轨的一个重要标志就是制度、流程是否被公司员工了解、熟悉、掌握和执行,是否有监督和保障措施。让员工熟悉、掌握各类制度、流程,不但是保证工作质量的需要,也是满足公司长远发展和员工快速成长的需要。事实证明,没有一套科学完整、切合实际的制度体系,管理工作和员工的行为就不能做到制度化、规范化、程序化,就会出现无序和混乱,就不会产生井然有序、纪律严明的团队。所以,要从我们的小团队做起,要运用各种形式,加大学习力度,抓执行力,抓落实兑现。
三是用有效的沟通激活团队建设,建立良好的工作氛围。把情况了解上来,把影响施加下去。
沟通的手段多种多样:
比如:聊天就是很好的方式之一。聊天那不是乱聊的意思,尤其在时机和话题的选择上。目的只有一个:拉近距离,融洽气氛,了解情况,施加影响。再如:还有比较喜欢用的就是娱乐,尤其是下棋、打牌、喝酒,这三项活动最能体现人的性格,想藏都藏不住。
性格无所谓优劣,最重要的是因人而异,善加利用。通过合理的组合,减少冲突,增强合力。
沟通是维护团队建设整体性的一项十分重要的工作,也可以说是一门艺术。如果说纪律是维护团队完整的硬性手段的话,那么沟通则是维护团队完整的软性措施,它是团队的无形纽带和润滑剂。沟通可以使团队建设中上情下达、下情上达,促进彼此间的了解;可以消除员工内心的紧张和隔阂,使大家精神舒畅,从而形成良好的工作氛围。因此,作为各单位负责人必须要保持团队内部上下、左右各种沟通渠道的畅通,以利于提高团队内部的士气,为各项工作的开展创造"人和"的环境。
四是树立服务意识。服务,这是团队建设的核心内容。
1.压制自己是头、有权发号施令的念头。
2.多地想的是对这个团体的责任,目的是要把工作做好。
3.要立足于服务,给团队成员创造出一个良好的工作环境。
4.要让团队成员放手工作,“错了,责任是我的,对了,功劳是你们的”
需要注意:
存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,存储在数据库中,经过第一次编译后调用时不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。存储过程是数据库中的一个重要对象。
MySQL存储函数(简称MySQL函数),是一种控制流程函数,属于数据库语言。
——百度百科
一、存储过程
在普通模式下获取数据,用户需要通过输入SQL指令与数据库进行交互;存储过程则是编写好的SQL指令,存储在数据库中,用户操作时只需调用存储过程,不用重新输入繁杂冗余的SQL指令。
那么,存储过程都有哪些优点呢?
(1)存储过程可以重复使用,减小开发人员的负担;
(2)对于网络上的服务器,可以减少网络流量,因为只需传输存储过程的名称即可;
(3)可以防止对表的直接访问,只需赋予用户对存储过程的访问权限。
在MySQL中,创建存储过程,使用CREATE PROCEDURE。
存储过程创建后,用CALL语句可以调用存储过程。在存储过程内还可以调用其他存储过程。
操作SQL命令创建存储过程CREATE PROCEDURE 存储过程名(参数种类1 参数1 数据类型1,[…] BEGIN 具体的procedure(处理) END查看数据库中的存储过程SHOW PROCEDURE STATUS\G查看具体的存储过程SHOW CREATE PROCEDURE 存储过程名\G调用(执行)存储过程CALL 存储过程名(参数1,…);删除存储过程DROP PROCEDURE 存储过程名变量声明DECLARE 变量名 数据类型;变量赋值SET 变量名= ; 其中,参数种类包括IN,OUT和INOUT。IN表示输入参数,OUT表示输出参数,INOUT表示既可以输入也可以输出。
参数的数据类型可以是MYSQL数据库中的任意类型。
案例如下:
(1)带输入和输出参数的存储过程:
/* 如果存在指定存储过程名则删除 */ mysql> drop procedure if exists sp1; Query OK, 0 rows affected /* 设置分隔符为// */ mysql> delimiter // mysql> create procedure sp1(in a int,in b int,out s int) -> begin -> set @ss=a+b; /* 用@符号加变量名的方式定义一个变量,与declare类似 */ -> set s=@ss; /* 语句体内可以执行多条sql,但必须以分号分隔 */ -> end// Query OK, 0 rows affected /* 将分隔符改回为分号; */ mysql> delimiter ; /* 调用该存储过程,注意:输入参数是一个值,而输出参数则必须是一个带@符号的变量 */ mysql> call sp1(3,5,@ret); Query OK, 0 rows affected mysql> select @ret; +------+ | @ret | +------+ | 8 | +------+ 1 row in set (2)既做输入又做输出参数的存储过程:
一、 APP字体大小,不随系统的字体大小变化而变化的方法
1、将字体大小的单位设置了dp,就可以固定字体大小不随系统设定的字号变化
sp和dp很类似但唯一的区别是,Android系统允许用户自定义文字尺寸大小(小、正常、大、超大等等),当文字尺寸是“正常”时1sp=1dp=0.00625英寸,而当文字尺寸是“大”或“超大”时,1sp>1dp=0.00625英寸。
2、代码设置(新)
● 新建类MyContextWrapper
import android.content.Context; import android.content.ContextWrapper; import android.content.res.Configuration; import android.content.res.Resources; import android.os.Build; import android.support.annotation.NonNull; import android.util.DisplayMetrics; public class MyContextWrapper extends ContextWrapper { public MyContextWrapper(Context base) { super(base); } @NonNull public static ContextWrapper wrap(Context context) { Resources resources = context.getResources(); Configuration newConfig = new Configuration(); DisplayMetrics metrics = resources.getDisplayMetrics(); newConfig.setToDefaults(); //如果没有设置densityDpi, createConfigurationContext对字体大小设置限制无效 newConfig.densityDpi = metrics.densityDpi; if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR1) { context = context.createConfigurationContext(newConfig); } else { resources.
要做技术工作,特别要做好技术,必不可少的就是学习。我碰到的所有技术牛人,无一例外的都拥有强烈的求知欲,不同的态度决定了自己可以走多远。
对于平时学习的态度,可以分为以下几个层次:
1、只关注项目本身,遇到不懂得问题后G或者B一下。2、会通过博客或者买书学习项目有关的框架或者技术。3、除了阅读和项目相关的书外,会查询是否有更好的框架或者技术来优化当前的架构。4、会看各类开源项目(Spring、Dubbo...)的源码,并搞懂其中的实现原理。5、紧跟技术前沿,为开源社区贡献自己的力量。
毫无疑问,大多数技术人员都在1和2两个层次上。能做到4,5的人至少是一家公司的大牛,或者技术圈的大神了,对技术需要浓厚的兴趣,同时具备奉献的精神。
学习技术,需要保持一个平常心,少被外界干扰,保持耐心很重要。在信息爆炸的时代,我们都可以站在巨人的肩膀上学习,看看不同的人的学习思路,选择最适合自己的方法。同时,学习是一件循序渐进的事情,比如先学习API结构、框架的设计,搞明白流程,再去搞明白更多的细节。
讲真,要把所有用到的框架的源码都看一遍了,不太现实,我们能做的是选择一些有代表性的源码进行阅读。做JAVA的同学,一定要去看Spring的源码,网上的源码解读一大堆,为什么大家都要读?因为Spring无论是设计思想,代码规范,还是设计模式,接口设计,类加载,都是非常优秀的源码。而且经历了从Spring1.x到5.x,几代程序员的洗礼,可以说已经无可挑剔。
学习源码的目的切记走火入魔,有些框架的源码可读性并不好,读后的现实意义并不大,将一个非常难懂的代码实现读懂并不能将它用到自己的项目中。我个人是实用主义者,读源码就是用来学习代码技巧,学习健全的错误异常机制,将这些好的经验用到自己的项目中。
而且对于技术学习,别动不动就要闹着学习源码,学习解决问题的思路更重要,大多数时候,我们缺乏的是明明看到有问题,但是不知道如何去解决它,所以可以多去学习一项技术或者一个框架的演变历史,看看作者是怎么应对和解决一个又一个问题的,别人踩过的坑,没必要自己非要再踩一遍。
最后,我们绝大多数人都是带着业务背景做技术的,如果你真能成为“业务人中最懂技术的,技术人中最懂业务的”复合型人才,也是一条很好的发展路线。
描二维码或手动搜索微信公众号【架构栈】: ForestNotes
欢迎转载,带上以下二维码即可
点击“阅读原文”,所有【架构栈】近期的架构文章汇总
↓↓↓
import matplotlib.pyplot as plt plt.figure(1) plt.plot([1,2,3]) plt.figure(2) plt.plot([3,2,1]) plt.show()
maven的两种可运行jar打包方式
1、内置依赖(插件maven-shade-plugin)
内置依赖,即maven打包过后,依赖的jar包也会被打包到一个jar文件上。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<!--可执行的main方法-->
<transformer>
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>cn.xxx.xxx</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2、外部依赖(插件maven-jar-plugin)
外部依赖,即maven打包过后,依赖的jar包copy一份到配置的路径。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<classesDirectory>target/classes/</classesDirectory>
<archive>
<manifest>
<mainClass>cn.jpush.esb.mq.ESBReceivedProcessor</mainClass>
<!-- 打包时 MANIFEST.MF文件不记录的时间戳版本 -->
<useUniqueVersions>false</useUniqueVersions>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
<manifestEntries>
<Class-Path>.</Class-Path>
</manifestEntries>
一、概述
1、ARP协议
地址解析协议,将IP地址转换为对应的mac地址,属链路层协议
数据包分为:
请求包(广播):本机IP地址、mac地址+目标主机IP地址应答包(单播):本机IP地址、mac地址+来源主机IP地址、mac地址 通信方式:
局域网内通信:
主机A和主机B通信过程:
(1)主机A先检查自己的缓存表中有没有主机B的IP地址和mac地址的对应关系,有就直接进行通信;如果没有,就在局域网广播一个arp请求包,包括主机A的IP地址、mac地址和主机B的IP地址。
(2)局域网内所有机器都会收到这个请求包,收到后与自己的ip地址对比一下,如果是自己的,就发送一个响应包,包括主机A的IP地址、mac地址和主机B的IP地址、mac地址;如果不是自己的,就丢掉。
局域网间通信:与上面过程类似,但是主机A要先和网关进行通信,再和主机B进行通信。
注意:a.两台主机的IP地址不在同一网段,需要通过网关来转发
b.涉及两个arp缓存表,一个是主机中存放的,另一个是网关处路由器设备自己的arp缓存表
2、 ARP欺骗
利用ARP协议的缺陷进行的一种非法攻击
二、ARP欺骗攻击原理
1、原理:主机接收到一个应答包之后,并不会验证自己是否发送过对应的arp请求包,也不会验证这个arp请求包是否可信,而是直接用应答包里的IP地址和mac地址的对应关系替换掉arp缓存表里原有的对应关系。
2、过程
攻击主机B向网关C发送一个应答包,包括主机A的IP地址、主机B的mac地址。同时,向主机A发送一个应答包,包括网关C的IP地址,主机B的mac地址。
这个时候,网关C就会将缓存表里主机A的mac地址换成主机B的mac地址,而主机a就会将缓存表里网关C的mac地址换成主机B的mac地址。
所以,网关C发送给主机A的消息全被主机B接收,主机A发送给网关C的消息也全被主机B接收,主机B就成为主机A和网关C通信的“中间人”。
三、ARP欺骗攻击的检测与防御
检测:
1、网络频繁掉线
2、网速突然变慢
3、使用arp -a命令查看的网关mac地址与真实的网关mac地址不同
4、使用嗅探软件发现局域网内存在大量arp应答包
防御:
1、绑定mac地址
2、使用静态arp缓存表
3、使用arp服务器,通过服务器来查找arp转换表来响应其他机器的广播
4、使用arp欺骗防护软件
四、ARP欺骗的危害
1、使同一网段内其他用户无法上网
2、可以嗅探到交换式局域网中的所有数据包
3、对信息进行篡改
4、可以控制局域网内任何主机
document.addEventListener("visibilitychange", () => { if(document.hidden) { // 页面被挂起,暂停播放 }else { // 页面呼出 } }); 我试了很多办法,都不可行。这个办法是我想到页面切换事件,试了试,安卓和苹果都可行。希望能帮到坑里的小伙伴····
MAC命令快速全局查找文件或文件夹,支持模糊搜索 首先第一步你需要知道怎么打开mac命令行:mac自带一个叫‘终端’的命令行工具,黑色的方形图标,有的叫‘bash’,打开它,在里面输入下面命令就可以了,比你手动查找快多了
描述:通过 find命令查找
语法:find ~ -iname “文件名*”
/** * 比如我要查找一个以‘vue-’开头的.zip文件, * 但是你忘了它的全名也忘了在那个文件夹, * 查找范围是‘~’节点以内 * 就可以用这种方式进行模糊搜索 */ find ~ -iname "vue-*.zip" 返回结果
/** * 然后它就把所有包含符合条件的文件和路径都打印出来了 */ /Users/shimh/Desktop/vue-demo.zip /Users/shimh/Downloads/vue-devtools-master.zip 这个不但能查找文件,还能查找文件夹
/** * 比如我要查找所有包含‘vue’的文件或文件夹 */ find ~ -iname "*vue*" 返回结果
/** * 结果它找到了所有包含‘vue’的文件或文件夹 */ /Users/shimh/.vue-templates /Users/shimh/.vue-templates/webpack-simple/template/src/App.vue /Users/shimh/Downloads/vue-devtools-master.zip /Users/shimh/Downloads/vue.js 方法总结
find方式很简单但是需要一点专业知识,需要知道一些正则的基本常识,需要指定路径范围,搜索的名字需要加引号等等,所以它不是最快捷的,下面这个是更快捷的查找方式:mdfind
描述:通过 mdfind命令查找
语法:mdfind -name 文件名
/** * 比如我要查找所有包含‘屏’的文件或文件夹 */ mdfind -name 屏 返回结果
/** * 看,我直接输入我要找的关键字‘屏’ * 就把所有文件和文件夹都输出出来了,是不是很方便 */ /Users/shimh/Desktop/Fw_ 大屏监控修改需求 /Users/shimh/Desktop/Fw_ 大屏监控修改需求/屏幕快照 2018-06-21 下午12.
使用selenium获取ajax加载的页面信息 实验网站:豆瓣电影剧情片
主要使用模块:
selenium (pip install selenium)lxml (pip install lxml) 主要思路:因为直接使用selenium访问豆瓣页面是不行的,需要让selenium执行一段js脚本滑动滚动条,才能使豆瓣页面刷新,获取到需要的内容。
代码如下
""" 使用selenium提取豆瓣电影剧情片数据 """ from selenium import webdriver from lxml import etree import time import json class DouBanMovieSelenium: """ 豆瓣电影 """ def __init__(self): self.url = "https://movie.douban.com/typerank?type_name=%E5%89%A7%E6%83%85&type=11&interval_id=100:90&action=" self.driver = webdriver.Chrome("F:\python自动化\chromedriver.exe") def load_page(self): """ 加载页面 """ self.driver.get(self.url) time.sleep(3) # 向下滚动1000像素 js = "window.scrollBy(0, 1000)" # 滚动到当前页面底部 # js = "window.scrollTo(0,document.body.scrollHeight)" self.driver.execute_script(js) time.sleep(3) # self.driver.save_screenshot("1.jpg") # time.sleep(1) self.driver.execute_script(js) time.sleep(3) # self.driver.save_screenshot("2.jpg") self.
九、设计模式
88. 说一下你熟悉的设计模式?
参考:常用的设计模式汇总,超详细!
89. 简单工厂和抽象工厂有什么区别?
简单工厂模式:
这个模式本身很简单而且使用在业务较简单的情况下。一般用于小项目或者具体产品很少扩展的情况(这样工厂类才不用经常更改)。
它由三种角色组成:
工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑,根据逻辑不同,产生具体的工厂产品。如例子中的Driver类。
抽象产品角色:它一般是具体产品继承的父类或者实现的接口。由接口或者抽象类来实现。如例中的Car接口。
具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现,如例子中的Benz、Bmw类。
来用类图来清晰的表示下的它们之间的关系:
抽象工厂模式:
先来认识下什么是产品族: 位于不同产品等级结构中,功能相关联的产品组成的家族。
图中的BmwCar和BenzCar就是两个产品树(产品层次结构);而如图所示的BenzSportsCar和BmwSportsCar就是一个产品族。他们都可以放到跑车家族中,因此功能有所关联。同理BmwBussinessCar和BenzBusinessCar也是一个产品族。
可以这么说,它和工厂方法模式的区别就在于需要创建对象的复杂程度上。而且抽象工厂模式是三个里面最为抽象、最具一般性的。抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象。
而且使用抽象工厂模式还要满足一下条件:
系统中有多个产品族,而系统一次只可能消费其中一族产品
同属于同一个产品族的产品以其使用。
来看看抽象工厂模式的各个角色(和工厂方法的如出一辙):
抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java中它由具体的类来实现。
抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。
十、Spring / Spring MVC
90. 为什么要使用 spring?
1.简介
目的:解决企业应用开发的复杂性
功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能
范围:任何Java应用
简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
2.轻量 从大小与开销两方面而言Spring都是轻量的。完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布。并且Spring所需的处理开销也是微不足道的。此外,Spring是非侵入式的:典型地,Spring应用中的对象不依赖于Spring的特定类。
3.控制反转 Spring通过一种称作控制反转(IoC)的技术促进了松耦合。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为IoC与JNDI相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。
4.面向切面 Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。
5.容器
Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建——基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一个新的实例——以及它们是如何相互关联的。然而,Spring不应该被混同于传统的重量级的EJB容器,它们经常是庞大与笨重的,难以使用。
6.框架
Spring可以将简单的组件配置、组合成为复杂的应用。在Spring中,应用对象被声明式地组合,典型地是在一个XML文件里。Spring也提供了很多基础功能(事务管理、持久化框架集成等等),将应用逻辑的开发留给了你。
所有Spring的这些特征使你能够编写更干净、更可管理、并且更易于测试的代码。它们也为Spring中的各种模块提供了基础支持。
91. 解释一下什么是 aop?
AOP(Aspect-Oriented Programming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理和透明的持续性也是如此。这种散布在各处的无关的代码被称为横切(cross-cutting)代码,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。
而AOP技术则恰恰相反,它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。AOP代表的是一个横向的关系,如果说“对象”是一个空心的圆柱体,其中封装的是对象的属性和行为;那么面向方面编程的方法,就仿佛一把利刃,将这些空心圆柱体剖开,以获得其内部的消息。而剖开的切面,也就是所谓的“方面”了。然后它又以巧夺天功的妙手将这些剖开的切面复原,不留痕迹。
使用“横切”技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。比如权限认证、日志、事务处理。Aop 的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。正如Avanade公司的高级方案构架师Adam Magee所说,AOP的核心思想就是“将应用程序中的商业逻辑同对其提供支持的通用服务进行分离。”
92. 解释一下什么是 ioc?
IOC是Inversion of Control的缩写,多数书籍翻译成“控制反转”。
1996年,Michael Mattson在一篇有关探讨面向对象框架的文章中,首先提出了IOC 这个概念。对于面向对象设计及编程的基本思想,前面我们已经讲了很多了,不再赘述,简单来说就是把复杂系统分解成相互合作的对象,这些对象类通过封装以后,内部实现对外部是透明的,从而降低了解决问题的复杂度,而且可以灵活地被重用和扩展。
前言
学习STM32CUBEMX工具的下载与安装,学会从st官网(www.st.com)查找与下载资料。
示例详解
STM32CUBEMX 下载 进入st官网(www.st.com),在官网的网页搜索框中输入STM32cubeMX 在跳转后面网页中,点 Get Software 网页自动跳转到尾部,选选最高版本(如图中5.0.1) 在弹出的界面中点ACCEPT,然后输入用户名及邮箱地址(用于接收下载地址),勾选I have…后点DOWNLOAD 此时网页显示界面如下,登入邮箱,去查收下载地址,在接收到的邮件中直接点击DownLoad Now 网页自动加载,然后自动下载 stm32cubemx 工具!! STM32CUBEMX安装,安装工作相当简单,全程NEXT 即可!! 解压下载完后的ZIP文件包,双击里面的.EXE文件 在出现的对话框中直接NEXT 勾选 I accept .. 然后NEXT 勾选 I have .. 然后NEXT 指定安装路径后,然后NEXT 直接NEXT进入安装 安装完成后直接NEXT, 然后DONE,安装完成!! OK,本期实验完成!下期见!同时如果大家有什么疑问或是有想了解的其它内容,也欢迎大家留言!!最后喜欢这个公众号的同学们记得加关注了,每天都会有技术干货推出!!
关注十三公众号
文中资料下载,在公众号里给十三发消息:
下载|STM32基础系列教程0
一,背景,
axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,它本身具有以下特征:
从浏览器中创建 XMLHttpRequest
从 node.js 发出 http 请求
支持 Promise API
拦截请求和响应
转换请求和响应数据
取消请求
自动转换JSON数据
客户端支持防止 CSRF/XSR
二,场景
每次都要在请求中加入,token ,判断是否登陆,如果vue系统中,所有的请求都加入token,比较麻烦,
有没有,每次发送求加入,vue 提供了一种方法,拦截器
三,使用与配置
在config 中,加入 axios.js
import axios from 'axios' // 配置默认的host,假如你的API host是:http://api.htmlx.club // 添加请求拦截器 axios.interceptors.request.use(function (config) { // 在发送请求之前做些什么 if (window.localStorage.getItem('access-token')) { config.headers.Authorization = window.localStorage.getItem('access-token'); } console.log(window.localStorage.getItem('access-token')); return config }, function (error) { // 对请求错误做些什么 return Promise.reject(error) }); // 添加响应拦截器 axios.interceptors.response.use(function (response) { // 对响应数据做点什么 return response }, function (error) { // 对响应错误做点什么 return Promise.
一、重投影残差 1.1基本概念 重投影残差,按照字面意思解释就是在第二次重新投影的二维像素点与第一次投影得到的像素点之间的残差(欧式距离)大小,残差的大小反映的就是测量仪器的精度以及外界因素对测量结果的干扰,即测量误差的大小。
如下图所示: 假设P是世界坐标系中的一个三维点(真实物点),第一次投影指的就是双目相机C1、C2拍摄时,P点投影到二维像平面上所捕获到的图像点,即图中的P1和P2点;然后利用双目视觉原理,针对P1、P2这对匹配点以及标定求出的内外、畸变参数等等,可以求出一个三维点(理论值);然后利用求出来的三维点与相机的位姿关系进行第二次投影得到P’2点;一般用重投影点P’2与获取的二维像点P2的欧式距离e值的大小反映的就是重投影误差的大小。
二、关键坐标系之间的转换 2.1 像素坐标系与图像坐标系 (u , v)表示的是像素坐标,单位Pixel;
(x , y)表示的是图像坐标,单位mm;
(u0 , v0)表示的是光心位置,有时候表示为(Cx,Cy);
dx , dy分别表示的是每个像素在横纵坐标的实际物理尺寸,单位mm;
2.2 图像坐标系与相机坐标系 以上公式最后的f,根据标定数据,在x和y方向分别以fx和fy代入,注意这里的fx和fy表示的是实际物理长度,单位mm,转换过程(三维坐标->像素坐标)如下图所示,不过有的情况标定得到得是实际长度(mm),则最后得fx和fy还需要除去dx、dy:
2.3 统一坐标重投影计算 如果世界坐标系与相机坐标系不统一的话,在进行透视投影之前需要把世界坐标系下的三维点云通过外方位参数[R|T]统一到相机坐标系下,在转换为像平面像素坐标,具体公式如下:
拆分:
R、t:世界坐标系相对于相机坐标系的外方位参数;
(X,Y,Z):世界坐标系下的坐标;
(x,y,z):转换的相机坐标系下的坐标;
(u,v):像素坐标。
2.4 残差计算 (u1,v1)记为获取的二维图像的匹配点,通过畸变矫正(undistortPoints())之后的结果,还要进行立体矫正(stereoRectify())
结果记为(x,y)(图像坐标),设(u,v)为矫正之后的像素坐标:
u = x/dx + Cx
v = y/dy + Cy
最后将得到的(u,v)和上式中的(u’,v’)做欧式计算,结果为残差值的大小
code: https://download.csdn.net/download/qq_39707351/11201279 Results: 按顺序依次为,三维点坐标,重投影像素坐标,匹配点像素坐标,残差大小(pixel)
在开发项目当中,不少也会遇到导入导出Excel表格。然而,没有弄过的小白,估计抓破头皮,都不一定能想得出来怎么实现,但是百度是个好东西。本人也通过百度,最终做出来了。好了,废话不多说,哥要开始表演啦,开好啦!
1、需要下载PHPExcel的SDK。我已经放在网盘中了,还没下载好的朋友,可以去下载哦。PHPExcel下载 ,提取码:engi
2、步骤: 把下载好的PHPExcel,放在verdor的根目录哦
html: php:
<?php
namespace app\admin\controller;
use think\Db;
use think\Request;
use think\Controller;
class Message extends Controller
{
public function index(){
return $this->fetch(); }
/**
* 导出excel文件
*/
public function excel_data(){
ob_clean();
vendor("PHPExcel.PHPExcel"); $objPHPExcel = new \PHPExcel();
$objProps = $objPHPExcel->getProperties();
$modelname = "留言表" . date('Y-m-d');
$showdata = db('message')->order('message_id desc')->select();
if (!$showdata) {
echo '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
echo '<script type="text/javascript">alert("无记录");history.go(-1);</script>';
exit;
} $objPHPExcel->getActiveSheet()->getColumnDimension('A')->setWidth(5);
$objPHPExcel->getActiveSheet()->getColumnDimension('B')->setWidth(15);
$objPHPExcel->getActiveSheet()->getColumnDimension('C')->setWidth(30);
ctrl + g
TextMesh Pro是Unity默认文本组件的替代品。TextMesh Pro和默认组件一样拥有高性能,它使用了完全不同的Signed Distance Field(SDF)渲染技术,该技术最初由Valve在《军团要塞2》中使用。TextMesh Pro能够很轻松就能让文本看起来更美观,还提供了更高级的控制功能,你可以通过检视窗口和脚本控制文本效果。
当你在项目中使用TextMesh Pro,它拥有改进的视觉效果。由于使用SDF渲染技术,你可以轻松修改文本的效果,无需重新制作字体。每个TextMesh Pro组件都附带可以调整的材质,从而修改文本的风格。TextMesh Pro还具有更好的控制功能。TextMesh Pro组件包含所有原始文本组件拥有的变量以及更多其它变量。
一、有两个TextMesh Pro组件可用:
1. 添加一个新的TextMesh Pro文本对象,它与网格渲染器一起工作:“GameObject->3D Object->TextMeshPro Text”。
2. 添加一个与新UI一起工作的TextMesh Pro组件,请转到:“GameObject->UI-”> TextMeshProText”
二、TextMesh Pro组件分为两个部分:文本输入( Text Input Box)和字体设置( Font Settings)
1.文本输入Text Input Box
在此区域键入要呈现的文本。可以输入多行文本,在键盘上按<Enter>或输入特殊字符\n。
<b>Bold</b>
<i>Italics</i>
<u>Underline</u>
<s>Strikethrough</s>
<sup>Superscript</sup>
<sub>Subscript</sub>
<size=48>Point size 48</size>
<size=+18>Point size increased by 18</size>
<size=-18>Point size decreased by 18</size>
<pos=5.5>Characters positioned about 5.5 characters from left side.
<color=yellow>Yellow text</color>
<#00ff00>Green text</color>
2.字体设置Font Settings
Font Asset:这是TextMeshPro字体资源。
Font Style:对文本应用全局样式,粗体、斜体等
改了个昵称
原来考虑到要把名字取可爱一点,叫“小巫女格格”。整体来说是在我匮乏的词汇库里,找出了一个代表我想法又不失幼稚的名字。
现在作为人民教师的我显然不能被同学们发现我这个神奇的名字,所以我把“小”给去掉了。
今天很高兴第102次打开重装的unity。
估计我需要仙人给我打通任督二脉,才能在剩下的时间里写出一份过关的paper。
还有我们单位的Dr.yu的真的很像我老爸,看着他我就倍感亲切。
第 10 章 类 要将注意力放到代码组织的更高层面,才能得到整洁的代码。
10.1 类的组织 遵循标准的 Java 约定,类应该从一组变量列表开始。如果有公共静态变量,应该先出现。然后是私有静态变量,以及私有实体变量。很少会有公共变量。 公共函数应跟在变量列表之后。我们喜欢把由某个公共函数调用的私有工具函数紧随在该公有函数后面。这符合了自顶向下原则,让程序读起来就像一篇报纸文章。 封装 若同一程序包内的某个测试需要调用一个函数或变量,我们就会将该函数或变量置为受保护或在整程序包内可访问。然而,我们首先会想办法使之保有隐私。放松封装总是下策。
10.2 类应该短小 关于类的第一条规则是类应该短小。第二条规则是还要更短小。 对于函数,我们通过计算代码行数衡量大小。对于类,我们采用不同的衡量方法,计算权责(responsibility)。 类的名称应当描述其权责。实际上,命名正是帮助判断类的长度的第一个手段。如果无法为某个类命以精确的名称,这个类大概就太长了。类名越含混,该类越偶可能拥有过多权责。 我们也应该能够用大概 25 个单词简要描述一个类,且不用“若(if)”、“与(and)”、“或(or)”或者“但(but)”等词汇。如果用若、与、或、但就说明类有太多权责。
10.2.1 单一权责原则 单一权责原则(SRP)认为,类或模块应有且只有一条加以修改的理由。该原则既给出了权责的定义,又是关于类的长度的指导方针。类只应有一个权责—只有一条修改的理由。 鉴别权责(修改的理由)常常帮助我们在代码中认识到并创建出更好的抽象。 系统应该由许多短小的类而不是少量巨大的类组成。每个小类封装一个权责,只有一个修改的原因,并与少数其他类一起协同达成期望的系统行为。
10.2.2 内聚 类应该只有少量实体变量。类中的每个方法都应该操作一个或多个这种变量。通常而言,方法操作的变量越多,就越黏聚到类上。如果一个类中的每个变量都被每个方法所使用,则该类具有最大的内聚性。 一般来说,创建这种极大化内聚类是既不可取也不可能的;另一方面,我们希望内聚性保持在较高位置。内聚性高,意味着类中的方法和变量互相依赖、互相结合成一个逻辑整体。 保持函数和参数列表短小的策略,有时会导致为一组子集方法所用的实体变量数量增加。出现这种情况时,往往意味着至少有一个类要从大类中挣扎出来。你应当尝试将这些变量和方法分拆到两个或多个类中,让新的类更为内聚。
10.2.3 保持内聚性就会得到许多短小的类 当类丧失了内聚性,就拆分它! 将大函数拆分成许多小函数,往往也是将类拆分为多个小类的时机。程序会更加有组织,也会拥有更为透明的结构。 重构后的程序更长的原因:其一,重构后的程序采用了更长、更有描述性的变量名。其二,重构后的程序将函数和类声明当作是给代码添加注释的一种手段。其三,我们采用了空格和格式技巧让程序更可读。
10.3 为了修改而组织 出现了只与类的一小部分有关的私有方法行为,意味着存在改进空间。 开放-闭合原则(OCP):类应当对扩展开放,对修改封闭。 隔离修改 部件之间的解耦代表着系统中的元素互相隔离得很好。隔离也让对系统每个元素的理解变的更加容易。 通过降低连接度,我们的类就遵循了另一条类设计原则,依赖倒置原则(Dependency Inversion Principle,DIP)。本质而言,DIP 认为类应当依赖于抽象而不是依赖于具体细节。
10.4 文献 转载于:https://www.cnblogs.com/zhangmiao14/p/10598298.html
1、下载hadoop并设置环境变量
HADOOP_HOME=F:\path_to\hadoop 在Path环境变量后追加 ;%HADOOP_HOME%\bin 2、下载winutil,并把winutils.exe和hadoop.dll文件复制到bin目录下
3、在idea中新建一个项目,导入hadoop包
步骤:右键项目名称->open moudle setting->点击右中上角“+”号选择1.JAR or D....
选择hadoop安装目录选择hadoop/share/hadoop 全选该目录下的所有目录以及common下的lib
包
MLPclassifier又称多层感知机Multiple layers perception或神经网络,在sklearn库中的该分类器有以下参数:
from sklearn.neural_network import MLPClassifier; model = MLPClassifier( hidden_layer_sizes=(100, ), activation=’relu’, solver=’adam’, alpha=0.0001, batch_size=’auto’, learning_rate=’constant’, learning_rate_init=0.001, power_t=0.5, max_iter=200, shuffle=True, random_state=None, tol=0.0001, verbose=False, warm_start=False, momentum=0.9, nesterovs_momentum=True, early_stopping=False, validation_fraction=0.1, beta_1=0.9, beta_2=0.999, epsilon=1e-08, n_iter_no_change=10);
IMEI码由15-17位数字组成。
第一部分 TAC,Type Allocation Code,类型分配码,由8位数字组成(早期是6位),是区分手机品牌和型号的编码,该代码由GSMA及其授权机构分配。其中TAC码前两位又是分配机构标识(Reporting Body Identifier),是授权IMEI码分配机构的代码,如01为美国CTIA,35为英国BABT,86为中国TAF。
第二部分 FAC,Final Assembly Code,最终装配地代码,由2位数字构成,仅在早期TAC码为6位的手机中存在,所以TAC和FAC码合计一共8位数字。FAC码用于生产商内部区分生产地代码。
第三部分 SNR,Serial Number,序列号,由第9位开始的6位数字组成,区分每部手机的生产序列号。
第四部分 CD,Check Digit,验证码,由前14位数字通过Luhn算法计算得出。
第五部分 SVN,Software Version Number,软件版本号,区分同型号手机出厂时使用的不同软件版本,仅在部分品牌的部分机型中存在。
转自:https://www.cnblogs.com/bohr/p/7093392.html 随机生成IMEI码
private static String getIMEI() {// calculator IMEI int r1 = 1000000 + new java.util.Random().nextInt(9000000); int r2 = 1000000 + new java.util.Random().nextInt(9000000); String input = r1 + "" + r2; char[] ch = input.toCharArray(); int a = 0, b = 0; for (int i = 0; i < ch.
如果你其他方法都试过了,看看自己有没有保存代码,不点保存运行会出错。
今天给人装了Win7系统,由于是2018年产的笔记本,一时间找不到Win7的驱动,只能使用万能驱动助理(WanDrv)来安装驱动,安装之后,就带上了一个垃圾:2345浏览器。
卸载这个垃圾之后,发现IE主页被锁死(Chrome倒没事),而且不是以前遇过的那种快捷方式尾巴病毒(尾巴病毒清除请参考我的另一篇博文:hao123.com劫持),
具体的病征就是:可以在IE中设置首页,但设置完之后,立马恢复为2345.com,根据无法保存。
试过了网上搜索的办法,没一个可行,包括360、Windows清理助手、注册表修改首页、火绒。。。
后来发现这解决方法也是挺巧合的,安装火绒之后,在IE中设置主页,火绒提示注册表被修改,是否阻止操作,还提示了注册表路径:
HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\EUPP\BackupHomePage 仔细一看,发现不对啊,怎么会是BackupHomePage呢?怎么看都不像平常的主页注册表项。。。
然后就试着把这个注册表项给删除了,然后就发现世界已经和平了,IE首页可以随便修改了,2345那个垃圾浏览器终于删干净了。
转载于:https://www.cnblogs.com/chenshao/p/10591802.html
使用两种方法构建模型,一种是如下所示方法,构建一个VGG16网络:
model = Sequential() model.add(Conv2D(32, (3, 3), strides=(1, 1), input_shape=(299, 299, 3), padding='same', activation='relu', kernel_initializer='uniform')) model.add(Conv2D(32, (3, 3), strides=(1, 1), padding='same', activation='relu', kernel_initializer='uniform')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Conv2D(64, (3, 2), strides=(1, 1), padding='same', activation='relu', kernel_initializer='uniform')) model.add(Conv2D(64, (3, 3), strides=(1, 1), padding='same', activation='relu', kernel_initializer='uniform')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Conv2D(128, (3, 3), strides=(1, 1), padding='same', activation='relu', kernel_initializer='uniform')) model.add(Conv2D(128, (3, 3), strides=(1, 1), padding='same', activation='relu', kernel_initializer='uniform')) model.add(Conv2D(128, (3, 3), strides=(1, 1), padding='same', activation='relu', kernel_initializer='uniform')) model.add(MaxPooling2D(pool_size=(2, 2))) model.
神经网络超参数有哪些? 神经网路中的超参数主要包括1. 学习率 ηη,2. 正则化参数 λλ,3. 神经网络的层数 LL,4. 每一个隐层中神经元的个数 jj,5. 学习的回合数EpochEpoch,6. 小批量数据 minibatchminibatch 的大小,7. 输出神经元的编码方式,8. 代价函数的选择,9. 权重初始化的方法,10. 神经元激活函数的种类,11.参加训练模型数据的规模 这十一类超参数。
隐藏层层数和每层神经元个数的设定 有一般经验公式。
详情请看BP神经网络隐藏层节点数如何确定
注意 数据正则化检查结果数据预处理数据规范化
注意数据归一化,数据标准化,正则化的区别
详情请看我搭的神经网络不work该怎么办!看看这11条新手最容易犯的错误 sklearn.MLPClassifier的主要参数 hidden_layer_sizes : tuple, length = n_layers - 2, default (100,)
The ith element represents the number of neurons in the ith hidden layer.
用于设置隐藏层大小,很重要。可以自动调参
activation : {‘identity’, ‘logistic’, ‘tanh’, ‘relu’}, default ‘relu’
Activation function for the hidden layer.
‘identity’, no-op activation, useful to implement linear bottleneck, returns f(x) = x
XAMPP启动数据库时,如果本地已经安装过MYSQL数据库,则无法正常启动,此时需要改变注册表的路径,具体如图所示:
将上图ImagePath路径改为:D:\XAMPP\mysql\bin(在你所安装的XAMPP安装文件夹里面)
如果想要再使用本地的MYSQL时,再将ImagePath路径改回来即可。
注意:
1.如果改回来以后不能运行MYSQL服务,可以考虑运行一下本地MYSQL中bin文件夹下的mysql.exe和mysqld.exe即可。
2.有些博客采用的方法提到了mysqld-nt.exe这个文件,而新版本的MYSQL中没有mysqld-nt.exe这个文件,所以直接运行mysql.exe和mysqld.exe就行。
第一步:树莓派断电,把sd卡取出,用读卡器连接到电脑上,把里面的原有的config.txt备份成其他名字的文件 第二步:重新建个config.txt 里面内容如下: hdmi_force_hotplug=1 config_hdmi_boost=4 hdmi_group=2 hdmi_mode=9 hdmi_drive=2 hdmi_ignore_edid=0xa5000080 disable_overscan=1 第三步:重新放到板子里面就可以,搞定
原文地址:https://blog.csdn.net/lichuangcsdn/article/details/80842223
1、首先新建第一个Student类
/**
* 排序测试 通过实现Comprable的compareTo方法进行排序
*/
public class Student implements Comparable<Student>{
private String name;
private Integer age; //排序字段
private Long time; //排序字段
public Student(){}
public Student(String name, Integer age,Long time) {
this.name = name;
this.age = age;
this.time = time;
}
//此处省略了getter和setter方法
@Override
public int compareTo(Student o) {
if (this.age > o.age) {
return 1;
}
if (this.age.equals(o.age)) {
if (this.time > o.time) {
return 1;
}
if (this.
js1.js引入js2.js,两个文件同目录
方法一:
document.write("<script type='text/javascript' src='js2.js'></script>"); 方法二:
import 'js2.js';
KNN 最邻近分类算法: (近邻取样)
邻近算法,或者说K最近邻(kNN,k-NearestNeighbor)分类算法是机器学习分类技术中最简单的方法之一。
所谓K最近邻,就是k个最近的邻居的意思,说的是每个样本都可以用它最接近的k个邻居来代表。
属于监督学习,有类别标记,且KNN是惰性学习。叫做Memory-based learning、也叫instance-based learning. 他没有明显的前期训练过程,在程序运行之后,把数据加载到内存后,不需要进行训练就可以分类。
算法实现:
1、计算出每一个样本点与测试点的距离
2、选取距离最近的K个样本,并获取他们的标签 label
3、然后找出K个样本中数量最多的标签,返回该标签
KNN的本质是基于一种数据统计的方法。
下面的是KNN案例的应用:手写数字识别。
我这里的案例是文本格式。没有图片转换的步骤。
素材模型:(源码+素材最后会贴上githup的链接)
KNN 手写数字识别 实现思路:
将测试数据转换成只有一列的0-1矩阵形式 将所有(L个)训练数据也都用上方法转换成只有一列的0-1矩阵形式
把L个单列数据存入新矩阵A中——矩阵A每一列存储一个字的所有信息
用测试数据与矩阵A中的每一列求距离,求得的L个距离存入距离数组中
从距离数组中取出最小的K个距离所对应的训练集的索引 拥有最多索引的值就是预测值
第一步:
导入模块:
import os,time,operator #导入os内置库来读取文件名 导入time来测试效率 import pandas as pd #导入数据处理库pandas 安装方法pip install pandas import numpy as np #导入科学计算库numpy 安装方法pip install numpy import matplotlib.pyplot as plt #导入绘图库matplotlib 安装方法pip install matplotlib 第二步:
引入文件,定义一个读取数据的转换数据的函数
## print(len(tarining)) #1934个训练集 ## print(len(test)) #945个测试集 trainingDigits =r'D:\work\日常任务6机器学习\day2手写数字识别\trainingDigits' testDigits = r'D:\work\日常任务6机器学习\day2手写数字识别\testDigits' ## ↑数据路径 tarining = (os.
从 公众号上发现了 总结的深度学习画图工具,很实用:https://mp.weixin.qq.com/s/MMzvZA55Xb2sOA7rJiXiEw 1 NN-SVG 这个工具可以非常方便的画出各种类型的图,是下面这位小哥哥开发的,来自于麻省理工学院弗兰克尔生物工程实验室, 该实验室开发可视化和机器学习工具用于分析生物数据。
github地址:https://github.com/zfrenchee 画图工具体验地址:http://alexlenail.me/NN-SVG/ 可以绘制的图包括以节点形式展示的FCNN style,这个特别适合传统的全连接神经网络的绘制。
以平铺网络结构展示的LeNet style,用二维的方式,适合查看每一层featuremap的大小和通道数目。
以三维block形式展现的AlexNet style,可以更加真实地展示卷积过程中高维数据的尺度的变化,目前只支持卷积层和全连接层。
这个工具可以导出非常高清的SVG图,值得体验。
2 PlotNeuralNet 这个工具是萨尔大学计算机科学专业的一个学生开发的,一看就像计算机学院的嘛。
首先我们看看效果,其github链接如下,将近4000 star:
https://github.com/HarisIqbal88/PlotNeuralNet 看看人家这个fcn-8的可视化图,颜值奇高。
使用的门槛相对来说就高一些了,用LaTex语言编辑,所以可以发挥的空间就大了,你看下面这个softmax层,这就是会写代码的优势了。
其中的一部分代码是这样的,会写吗。
\pic[shift={(0,0,0)}] at (0,0,0) {Box={name=crp1,caption=SoftmaxLoss: $E_\mathcal{S}$ ,% fill={rgb:blue,1.5;red,3.5;green,3.5;white,5},opacity=0.5,height=20,width=7,depth=20}}; 相似的工具还有:https://github.com/jettan/tikz_cnn
3 ConvNetDraw ConvNetDraw是一个使用配置命令的CNN神经网络画图工具,开发者是香港的一位程序员,Cédric cbovar。
采用如下的语法直接配置网络,可以简单调整x,y,z等3个维度,github链接如下:
https://cbovar.github.io/ConvNetDraw/ 使用方法如上图所示,只需输入模型结构中各层的参数配置。
挺好用的不过它目标分辨率太低了,放大之后不清晰,达不到印刷的需求。
4 Draw_Convnet 这一个工具名叫draw_convnet,由Borealis公司的员工Gavin Weiguang Ding提供。
简单直接,是纯用python代码画图的,
https://github.com/gwding/draw_convnet 看看画的图如下,核心工具是matplotlib,图不酷炫,但是好在规规矩矩,可以严格控制,论文用挺合适的。
类似的工具还有:https://github.com/yu4u/convnet-drawer
5 Netscope 下面要说的是这个,我最常用的,caffe的网络结构可视化工具,大名鼎鼎的netscope,由斯坦福AILab的Saumitro Dasgupta开发,找不到照片就不放了,地址如下:
https://github.com/ethereon/netscope 左边放配置文件,右边出图,非常方便进行网络参数的调整和可视化。这种方式好就好在各个网络层之间的连接非常的方便。
其他 再分享一个有意思的,不是画什么正经图,但是把权重都画出来了。
http://scs.ryerson.ca/~aharley/vis/conv/ 看了这么多,有人已经在偷偷笑了,上PPT呀,想要什么有什么,想怎么画就怎么画 draw.io 还要别人推荐的这个
标题:激光样式
x星球的盛大节日为增加气氛,用30台机光器一字排开,向太空中打出光柱。
安装调试的时候才发现,不知什么原因,相邻的两台激光器不能同时打开!
国王很想知道,在目前这种bug存在的情况下,一共能打出多少种激光效果?
显然,如果只有3台机器,一共可以成5种样式,即:
全都关上(sorry, 此时无声胜有声,这也算一种)
开一台,共3种
开两台,只1种
30台就不好算了,国王只好请你帮忙了。
要求提交一个整数,表示30台激光器能形成的样式种数。
注意,只提交一个整数,不要填写任何多余的内容。
答案:2178309
解题思路:思路很简单,暴力搜索,30个灯光从左到右,从左边第一个开始,第一个可以开关,第二个要根据左边的灯光是否开启来取值,依次类推。
#include <iostream> using namespace std; long long ans; int sta[33]; void dfs(int x) { if(x == 31)//出口 { ans++; return ; } dfs(x+1);//递归 :默认设置当前所访问的灯不开 if(sta[x-1] == 0) { sta[x] = 1; dfs(x+1); sta[x] = 0;//回溯 } return ; } int main() { dfs(1); cout<<ans<<endl; return 0; }
题目 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
问总共有多少条不同的路径?
说明:m 和 n 的值均不超过 100。
示例 1:
输入: m = 3, n = 2 输出: 3 解释: 从左上角开始,总共有 3 条路径可以到达右下角。 1. 向右 -> 向右 -> 向下 2. 向右 -> 向下 -> 向右 3. 向下 -> 向右 -> 向右 示例 2:
输入: m = 7, n = 3 输出: 28 思路 使用动态规划,二维数组来解这道题,实际上每个位置需要的步数位其上和其左需要的步数相加,第一行和第一列初始为1
比如示例2中的数
1 1 1 1 1 1 1
1)添加jar <!-- 文件上传组件 --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> </dependency> 2)springmvc.xml
<!-- 定义文件上传解析器 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 设定默认编码 --> <property name="defaultEncoding" value="UTF-8"></property> <!-- 设定文件上传的最大值5MB,5*1024*1024 --> <property name="maxUploadSize" value="5242880"></property> </bean>
报错 Caused by: com.mysql.cj.exceptions.WrongArgumentException: The connection property 'useSSL' acceptable values are: 'TRUE', 'FALSE', 'YES' or 'NO'. The value 'false$serverTimezone=UTC' is not acceptable. at sun.reflect.GeneratedConstructorAccessor56.newInstance(Unknown Source) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:61) at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:105) at com.mysql.cj.conf.DefaultPropertySet.initializeProperties(DefaultPropertySet.java:202) at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:395) ... 10 common frames omitted Caused by: com.mysql.cj.exceptions.CJException: The connection property 'useSSL' acceptable values are: 'TRUE', 'FALSE', 'YES' or 'NO'. The value 'false$serverTimezone=UTC' is not acceptable. at sun.reflect.GeneratedConstructorAccessor55.newInstance(Unknown Source) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.
REDHAT AS4U4的X86_64系统,在系统的/VAR/LOG/MESSAGE日志中出现大量的truncating integer value to 32 bits信息,完整的信息如下:
Jun 18 11:22:10 billdb1 snmpd[26994]: send response:
Jun 18 11:22:10 billdb1 snmpd[26994]: truncating integer value to 32 bits
Jun 18 11:22:10 billdb1 snmpd[26994]: truncating uinteger value to 32 bits
Jun 18 11:22:10 billdb1 snmpd[26994]: truncating uinteger value to 32 bits
Jun 18 11:22:13 billdb1 snmpd[26994]: truncating integer value to 32 bits
Jun 18 11:22:13 billdb1 snmpd[26994]: truncating uinteger value to 32 bits
阿里云服务器安装Nginx以及配置Nginx域名映射 一、Nginx介绍 Nginx是一款轻量级的网页服务器、反向代理服务器。相较于Apache、lighttpd具有占有内存少,稳定性高等优势。它最常的用途是提供反向代理服务。
二、阿里云服务器安装Nginx 介绍:在Centos下,yum源不提供nginx的安装,可以通过切换yum源的方法获取安装。也可以通过直接下载安装包的方法,以下命令均需root权限执行:
首先安装必要的库(nginx 中gzip模块需要 zlib 库,rewrite模块需要 pcre 库,ssl 功能需要openssl库)。选定/usr/local为安装目录,以下具体版本号根据实际改变。
安装步骤:
1、安装gcc gcc-c++(如新环境,未安装请先安装) // 在/目录下进行安装即可 $ yum install -y gcc gcc-c++ 2、安装wget // 在/目录下安装即可 $ yum -y install wget 3、安装PCRE库 // 软件安装目录地址以个人习惯设置 $ cd /usr/local/software $ wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.36.tar.gz $ tar -zxvf pcre-8.36.tar.gz $ cd pcre-8.36 $ ./configure $ make && make install //如果报错: 在 linux 中执行 wget 命令提示 -bash: wget: command not found 解决方法 解决办法 yum -y install wget 4、安装SSL库 $ cd /usr/local/software $ wget http://www.
问题描述 现在开发项目,一般都会创建maven工程,用它来管理依赖实在是方便了,当然它还有其它用途。但是在实际的情况中往往会有重复依赖的问题,比如创建的工程A,依赖了b-1.0.jar,而b-1.0.jar又依赖了d-1.0.jar(这个我们本身是不能直接看到的),同时我们自己的工程又依赖了d-2.1.jar,或者工程A依赖了c-1.0.jar,c-1.0.jar依赖了d-2.0.jar,显然,d.jar有3个版本,3者之间是重复的,甚至是冲突的。如下图所示:
重复依赖会怎么样? 首先从工程角度来讲,引用了同一个Jar的不同版本,这肯定是依赖有问题,或者就是错误的。
其次,重复依赖,在项目启动过程当中可能会有一些警告信息。
当然,最重要的是引发代码异常,最常见的就是NoSuchMethod。
解决思路 寻找重复引用的jar。定位这些Jar在哪里被引用了。接下来需要分析舍与留,原则上保留高版本,大多数情况下是向下兼容的。但是不一定,有时候也得保留低版本,或者有时候两者都需要保留。如果是一个工程,其实处理起来还比较好处理。但是如果有多个工程,最终我们可能将所有的依赖合在一块儿。处理起来可能会稍微麻烦些,比如工程1依赖了2.1版本,工程2依赖了2.2版本,你把工程1的2.1的依赖去掉,但同时还需要把2.2的加在工程1上面,否则可能编译不通过。最重要的就是,调整之后,尽可能做全面测试。特别是一些间接依赖,如果去除的话,编译不会有问题,但运行起来会有问题。 具体解决过程 上述5个步骤,重点说一下1和2.
寻找重复引用的jar 观察法:把所有的jar依赖打包到同一个目录下,观察。运行法:运行阶段会报错,一旦报错,基本上就定位到了。扫描法:专业的测试人员,可以进行扫描jar包并统计。搜索法:依靠maven进行搜索,这个方法在接下来会讲到。 定位Jar被依赖的地方 在maven工程处打开命令行,输入:
mvn dependency:tree -Dverbose > tree.txt 这个命令会把这个工程pom.xml里面所有的依赖通过树的形状展示出来,tree.txt:
树形结构其实看得比较清楚,里面有一些关键信息,比如:
omitted for duplicate 这个意思是依赖是重复的,当然这个没有关系。
当然还有一些冲突提醒,上图没有,如下:
omitted for conflict with 0.5.3 显示就是这个版本与0.5.3这个版本冲突了,这个也是我上面说到的搜索法,你可以直接搜索“conflict”这个单词,就可以了。当然这种方式仅限单个工程。
拿到这棵树以后,怎么办呢?
前提是我们已经知道了哪个jar包冲突了,那直接就在文本里面搜索,找到不同版本的引用之处,然后慎重考虑之后,通过exclusions标签进行去除,如下:
<dependency> <groupId>jaxen</groupId> <artifactId>jaxen</artifactId> <version>1.1.1</version> <exclusions> <exclusion> <groupId>xerces</groupId> <artifactId>xercesImpl</artifactId> </exclusion> </exclusions> </dependency> 到此结束。去除的同时需要考虑的一些问题,在解决思路里面提及了一些。
单SpringBoot项目配置swaggerAPI文档 1.添加maven依赖
<!--Swagger-UI API文档生产工具--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency> 2.添加swagger配置类
@Configuration @EnableSwagger2 public class Swagger2 { /** * 创建API应用 * apiInfo() 增加API相关信息 * 通过select()函数返回一个ApiSelectorBuilder实例,用来控制哪些接口暴露给Swagger来展现, * 本例采用指定扫描的包路径来定义指定要建立API的目录。 */ @Bean public Docket createRestApi(){ com.google.common.base.Predicate<RequestHandler> selector1 = RequestHandlerSelectors.basePackage("com.cnczsq.mall.elephant.v1.controller"); com.google.common.base.Predicate<RequestHandler> selector2 = RequestHandlerSelectors.basePackage("com.cnczsq.mall.elephant.v2.controller"); return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() //为当前包下controller生成API文档 //单个配置controller //.apis(RequestHandlerSelectors.basePackage("com.cnczsq.mall.elephant.v1.controller")) //controller批量配 方式一 .apis(Predicates.or(selector1,selector2)) // controller批量配方式二 指定所有controller的都实现的一个接口,比如@RestController //.apis(RequestHandlerSelectors.withClassAnnotation(RestController.class)) // controller批量配方式三 指定所有controller路径的父级 //.apis(RequestHandlerSelectors.basePackage("com.cnczsq.mall.elephant")) // controller批量配方式四 指定所有ApiOperation注解方法 //.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) .paths(PathSelectors.any()) .build(); //添加登录认证 .
1.效果图 2.闪屏页逻辑及布局 2.1 activity_splash.xml <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:src="@drawable/splash" android:scaleType="centerCrop"/> <Button android:id="@+id/splash_btn_skip" android:layout_width="45dp" android:layout_height="32dp" android:text="跳过" android:textStyle="bold" android:textColor="#fff" android:background="#30000000" android:layout_gravity="right" android:layout_marginTop="30dp" android:layout_marginRight="30dp"/> </FrameLayout> 2.2 SplashActivity.java 通过Handler实现
public class SplashActivity extends AppCompatActivity { //跳过按钮 private Button btnSkip; private Handler handler = new Handler(); private Runnable runnableToLogin = new Runnable() { @Override public void run() { toLoginActivity(); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.
Java高级工程师面试题总结及参考答案
原链接地址:请点击地址Java团长
基于Node-Red树莓派智能车实现 特性: Android手机通过WiFi网络控制
进行图像传输,小车速度\转向\前后控制\灯光控制
智能车部分 树莓派3B500万像素树莓派摄像头Node-Red使用L298N电机驱动模块PCA9685 PWM模块Nrf24L01+PA+LNA无线模块智能车(两驱或者四驱)LED若干 遥控端部分 Android手机OTG线Arduino NanoNrf24L01+PA+LNA无线模块 通过Fritzing画的接线图 实现了
Android APP控制的效果 实际上背景是一个WebView,加载的网络视频流,树莓派搭建了一个小型服务
在这个背景上面左右上下滑动,能够控制云台实现那个方位的查看
然后左边绿色的是8向的控制按钮,能控制小车360度无死角运行,最下面的滑块是速度控制,因为我们使用了动力电池。
上方有个Switch,是控制使用局域网络还是使用Nrf24l01无线模块进行控制,右边是一个车灯的开关
这个项目做出来后,感觉很开心,也很有成就感,因为你能自己实现类似大疆无人机的控制效果!
虽然说是基于Node-RED的,无需多大的代码空间,但是这个原理是复制不来的,即使让我手动实现,那也是完全没有问题的,只是说Node-Red让树莓派的开发变得十分快捷 ,快速验证了一个功能是否能够实现
摘自:https://docs.docker.com/engine/reference/run/
Docker 运行参考 Docker进程运行在独立的容器中。一个容器就是一个独立运行在宿主机上的进程,宿主机可能是本机或者是远程机器。当执行 docker run命令时,容器会使用它自己的文件系统、自己的网络、自己的进程树、以脱离宿主机的方式独立运行。
本文详细介绍了如何使用docker run命令来在运行期定义容器内部资源。
常用类型 docker run 的基础用法类似:
$ docker run [OPTIONS] IMAGE[:TAG|@DIGEST] [COMMAND] [ARG...] docker run 必须指定一个镜像来生成容器。
一个镜像开发者可以定义以下相关内容:
以后台方式运行(detached)还是以前台方式运行(foreground)容器标识(--name 指定容器名称)网络设置在受限制的CPU和内存上运行 使用docker run可以添加或者覆盖镜像,默认被开发人员设置。另外,操作者几乎可以覆盖所有Docker运行期的默认值。操作者能够覆盖镜像和Docker运行时默认值,这就是为什么run比其他Docker命令拥有更多选项的原因。
操作者特有选项 只有操作者(执行docker run的人)可以使用一下选项:
前台还是后台显示:-d (detached),默认-d 等于 -d=true容器唯一标识设置:-- name;PIDIPC设置:--ipc网络设置重启策略(--restart)自动清除已停止的容器(--rm)运行期资源约束运行期优先级和Linux功能 分离式vs前台式 当启动一个docker容器时,你必须先决定是想前台式运行还是分离式运行:
-d=false 分离模式: 在后台运行程序, 会在控制台打印一个新的容器ID 分离方式 Detached[-d] 以分离式启动一个容器,你可以使用 -d=true 或者直接 -d 选项。根据设计描述,以分离式启动的所有容器当root进程执行容器退出命令时才会退出,如果指定了--rm选项还会删除容器。如果你使用了-d选项并同时使用了--rm,当容器退出了或者守护进程宕了,都会删除掉容器本身。
分离模式不要使用 service x start,例如下面这个命令试图启动一个nginx服务:
$ docker run -d -p 80:80 my_image service nginx start 启动nginx容器成功了,然而,它并没有采用分离容器的方式,因为root进程(service nginx start) 返回了,分离容器按设计停止。结果是,nginx服务启动了,但是不能用。相对的,启动一个nginx服务应该像这样:
$ docker run -d -p 80:80 my_image nginx -g 'daemon off;' 分离式启动的容器,需要输入/输出,需要使用网络连接或者共享数据卷。因为在 docker run之后容器不再监听命令行。如果想重新连接容器,使用 docker attach命令。
function UpperCase( const s: string ) :string;
说明:用于将 s 字符串中的所有小写字母转化为大写字母 其他字符不变
var
sss:string;
sss := 'w 我的asDgh';
showmessage( String.UpperCase(sss) );
结果:W 我的ASDGH
function LowerCase( const s: string ) : string;
说明:用于将s字符串中的所有大写字母转化为小写字母,其他字符不变
var
sss:string;
begin
sss := 'w 我的asDgh';
showmessage( String.LowerCase(sss) );
end;
结果:w 我的asdgh
1.封装类
import org.apache.commons.lang3.StringUtils; import org.apache.poi.ss.usermodel.*; import java.io.InputStream; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; /** * excel导入公共类 */ public class InExcelUtil { /*遍历excel文件流,将数据放入list集合当中*/ public static List<List<String>> getExcelStringList(InputStream in, int cellCount) throws Exception{ Workbook work = WorkbookFactory.create(in); if(work == null) throw new Exception("上传文件为空"); Row row = null; Cell cell = null; List<List<String>> list = new ArrayList<List<String>>(); //int sheetnum = work.getNumberOfSheets();//excel中sheet总数 Sheet sheet = work.getSheetAt(0);//获取excel中第一个sheet if(sheet != null){ int rowCount = sheet.getPhysicalNumberOfRows(); //获取总行数 for(int j=sheet.
1、关系运算符用于数值型、布尔型、字符型、字符串型数据的比较,运算结果是布尔型,关系运算符有: = 、 > 、>= 、< 、<=、 <> 、in 。
字符比较是字符ascii码的大小,字符串的比较是从左到右进行的。
例如
2.0 > 3.0 // 值为 false
'A' < 'a' //值为 true 1 >= 2 //值为false
3 <> 3.5 //值为true
'ab' > 'ac' 值为false ,从左到右比较,前一个字符相同,故比较后面的‘b’ 和‘c’
1 in [2,3] //值为false , in 用于判断一个元素是否在一个集合中
2,逻辑运算符
逻辑运算符又称为布尔运算符,用于对布尔类型的数据进行运算。主要有 not(非)、and (与)、(or)或、xor(异或)
abnot aa and ba or ba xor bfalsefalse truefalsefalseflasefalsetruetruefalsetruetruetruefalsefalsefalsetruetruetruetruefalsetruetruefalse 布尔运算具有短路计算功能,即从左往右计算,如果表达式的值已经确定,则立即终止计算,不再继续计算其他表达式的值
运算优先级遵照 级别高的先,低的后
1.括号()
2.函数
3. not + - (取正、负符号)
4.乘法类:*、/、div、mod、and、shl、shr
5.加法类:+、-、or、xor
nginx负载均衡的5种策略
nginx可以根据客户端IP进行负载均衡,在upstream里设置ip_hash,就可以针对同一个C类地址段中的客户端选择同一个后端服务器,除非那个后端服务器宕了才会换一个。
nginx的upstream目前支持的5种方式的分配
1、轮询(默认)
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
upstream backserver {
server 192.168.0.14;
server 192.168.0.15;
}
2、指定权重
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
upstream backserver {
server 192.168.0.14 weight=10;
server 192.168.0.15 weight=10;
}
3、IP绑定 ip_hash
每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。 #ip哈希化 就像是粘上去了,容易宕机
upstream backserver {
ip_hash;
server 192.168.0.14:88;
server 192.168.0.15:80;
}
4、fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。
upstream backserver {
server server1;
server server2;
fair;
}
5、url_hash(第三方)
按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。
upstream backserver {
server squid1:3128;
server squid2:3128;
hash $request_uri;
hash_method crc32;
}
在需要使用负载均衡的server中增加
proxy_pass http://backserver/;
upstream backserver{
上传证书完成后,需要修改nginx的配置,因为并不需要整站https访问,所以需要http和https访问共存,如下
upstream tomcat{ server 127.0.0.1:2080; } upstream tomcat_robot{ server 127.0.0.1:8080; } server { listen 80 ; listen 443 ssl; server_name www.xxxx.cn; # ssl on; http和https共存,必须注释 ssl_certificate cert/1528751974958.pem; ssl_certificate_key cert/1528751974958.key; ssl_session_timeout 5m; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; location / { proxy_pass http://127.0.0.1:8080; # root html; # index index.html index.htm; } } # server { # # listen 80; # server_name www.xxx.cn; #域名 # charset utf-8; # #charset koi8-r; # #access_log logs/host.
什么是springboot 用来简化spring应用的初始搭建以及开发过程 使用特定的方式来进行配置(propertites或yml文件)
创建独立的spring引用程序main方法运行
嵌入的tomcat无需部署war文件
简化maven配置
自动配置spring 添加对应功能starter自动化配置
springboot常用的starter有哪些 spring-boot-starter-web嵌入tomcat和webkaifa需要servlet与jsp支持 spring-boot-starter-data-jpa数据库支持 spring-boot-starter-data-redis数据库支持 spring-boot-starter-data-solr solr支持 mybatis-spring-boot-starter第三方的mybatis集成starter springboot自动配置的原理 在spring程序main方法中添加@SpringBootApplication或者@EnableAutoConfiguration 会自动去mavenzhong读取每个starter中的spring.factories文件,该文件配置了所有需要被创建spring容器中的bean springboot读取配置文件的方式 springboot默认读取配置文件为application.properties或者application.yml springboot集成mybatis的过程 添加mybatis的starter maven依赖 …mybatis-spring-boot-starter1.2.0
在mybatis的接口中添加@Mapper注解
在application.yml配置数据源信息
springboot如何添加【修改代码】自动重启功能
添加开发者工具·spring-boot-devtools
什么是微服务 以前的模式是所有的代码在同一个工程中 部署在同一个服务器中 同一个项目的不同模块不同功能互相抢占资源 微服务 将工程根据不同的业务规则拆分成微服务 微服务部署在不同的机器上 服务之间进行相互调用 java微服务的框架有dubbo(只能用来做微服务),springCloud(提供了服务的发现,断路器等) springcloud如何实现服务的注册和发现 服务在发布时 指定对应的服务名(服务名包括了IP地址和端口) 将服务注册到注册中心(eureka或者zookeeper) 这一过程时springcloud自动实现 只需要在main方法添加@EnableDisscoveryClient 同一个服务修改端口就可以启动多个实例 调用方法:传递服务名称通过注册中心获取所有的可用实例,通过负载均衡策略调用(ribbon和feign)对应的服务 ribbon和feign区别 Ribbon添加maven依赖 spring-starter-ribbon 使用@RibbonClient(value="服务名称") 使用RestTemplate调用远程服务对应的方法 feign添加maven依赖 spring-starter-feign 服务提供方提供对外接口 调用方使用 在接口上使用@FeignClient("指定服务名") Ribbon和Feign的区别 Ribbon和Feign都是用于调用其他服务,不过方式不同。 1、启动类使用的注解不同,Ribbon使用的时@RibbonClient,Feign用的时@EnableFeignClients 2、服务的指定位置不同,Ribbon是在@RibbonClient注解上声明,Feign则是在定义抽象方法的接口使用@FeignClient声明。 3、调用方式不同,Ribbon需要自己构建http请求,模拟http请求然后使用RestTemplate发送给其他服务,步骤相当繁琐。 Feign则是在Ribbon的基础进行了一次改进,采用接口的方式,将需要调用的其他服务的方法定义成抽象方法即可。 不需要自己构建http请求。不过要注意的是抽象方法的注解、方法签名要和提供服务的方法完全一致。 SpringCloud断路器的作用 当一个服务调用另一个服务由于网络原因或者自身原因出现问题时 ,调用者就会等待被调者的响应, 当更多的服务请求到这些资源时,导致更多的请求等待,这样就会发生连锁效应,断路器就是解决这一问题的。 断路器有完全打开状态: 一定时间内,达到一定的次数无法调用,并且多次检测没有恢复的迹象,断路器完全打开,那么下次的请求不会请求到该服务。 半开: 短时间内有回复迹象,断路器会将部分请求发送给服务,当能正常调用时,断路器关闭。 关闭: 当服务一直处于正常状态,能正常调用,断路器关闭。 如何使用springboot部署到不同的服务器 1、在一个项目中生成一个war文件。 2、将它部署到想要部署的服务器中(websphere或者weblogic或者Tomcat and so on) JPA和Hibernate有哪些区别 简而言之: 1、JPA是一个规范或者接口 2、Hibernate是JPA的一个实现 当我们使用JPA的时候,我们使用javax.
一、JVM结构
根据《java虚拟机规范》规定,JVM的基本结构一般如下图所示:
从左图可知,JVM主要包括四个部分:
1.类加载器(ClassLoader):在JVM启动时或者在类运行时将需要的class加载到JVM中。(右图表示了从java源文件到JVM的整个过程,可配合理解。 关于类的加载机制,可以参考http://blog.csdn.net/tonytfjing/article/details/47212291)
2.执行引擎:负责执行class文件中包含的字节码指令(执行引擎的工作机制,这里也不细说了,这里主要介绍JVM结构);
3.内存区(也叫运行时数据区):是在JVM运行的时候操作所分配的内存区。运行时内存区主要可以划分为5个区域,如图:
方法区(Method Area):用于存储类结构信息的地方,包括常量池、静态变量、构造函数等。虽然JVM规范把方法区描述为堆的一个逻辑部分, 但它却有个别名non-heap(非堆),所以大家不要搞混淆了。方法区还包含一个运行时常量池。
java堆(Heap):存储java实例或者对象的地方。这块是GC的主要区域(后面解释)。从存储的内容我们可以很容易知道,方法区和堆是被所有java线程共享的。
java栈(Stack):java栈总是和线程关联在一起,每当创建一个线程时,JVM就会为这个线程创建一个对应的java栈。在这个java栈中又会包含多个栈帧,每运行一个方法就创建一个栈帧,用于存储局部变量表、操作栈、方法返回值等。每一个方法从调用直至执行完成的过程,就对应一个栈帧在java栈中入栈到出栈的过程。所以java栈是现成私有的。
程序计数器(PC Register):用于保存当前线程执行的内存地址。由于JVM程序是多线程执行的(线程轮流切换),所以为了保证线程切换回来后,还能恢复到原先状态,就需要一个独立的计数器,记录之前中断的地方,可见程序计数器也是线程私有的。
本地方法栈(Native Method Stack):和java栈的作用差不多,只不过是为JVM使用到的native方法服务的。
4.本地方法接口:主要是调用C或C++实现的本地方法及返回结果。
二、内存分配
我觉得了解垃圾回收之前,得先了解JVM是怎么分配内存的,然后识别哪些内存是垃圾需要回收,最后才是用什么方式回收。
Java的内存分配原理与C/C++不同,C/C++每次申请内存时都要malloc进行系统调用,而系统调用发生在内核空间,每次都要中断进行切换,这需要一定的开销,而Java虚拟机是先一次性分配一块较大的空间,然后每次new时都在该空间上进行分配和释放,减少了系统调用的次数,节省了一定的开销,这有点类似于内存池的概念;二是有了这块空间过后,如何进行分配和回收就跟GC机制有关了。
java一般内存申请有两种:静态内存和动态内存。很容易理解,编译时就能够确定的内存就是静态内存,即内存是固定的,系统一次性分配,比如int类型变量;动态内存分配就是在程序执行时才知道要分配的存储空间大小,比如java对象的内存空间。根据上面我们知道,java栈、程序计数器、本地方法栈都是线程私有的,线程生就生,线程灭就灭,栈中的栈帧随着方法的结束也会撤销,内存自然就跟着回收了。所以这几个区域的内存分配与回收是确定的,我们不需要管的。但是java堆和方法区则不一样,我们只有在程序运行期间才知道会创建哪些对象,所以这部分内存的分配和回收都是动态的。一般我们所说的垃圾回收也是针对的这一部分。
总之Stack的内存管理是顺序分配的,而且定长,不存在内存回收问题;而Heap 则是为java对象的实例随机分配内存,不定长度,所以存在内存分配和回收的问题;
三、垃圾检测、回收算法
垃圾收集器一般必须完成两件事:检测出垃圾;回收垃圾。怎么检测出垃圾?一般有以下几种方法:
引用计数法:给一个对象添加引用计数器,每当有个地方引用它,计数器就加1;引用失效就减1。
好了,问题来了,如果我有两个对象A和B,互相引用,除此之外,没有其他任何对象引用它们,实际上这两个对象已经无法访问,即是我们说的垃圾对象。但是互相引用,计数不为0,导致无法回收,所以还有另一种方法:
可达性分析算法:以根集对象为起始点进行搜索,如果有对象不可达的话,即是垃圾对象。这里的根集一般包括java栈中引用的对象、方法区常良池中引用的对象
本地方法中引用的对象等。
总之,JVM在做垃圾回收的时候,会检查堆中的所有对象是否会被这些根集对象引用,不能够被引用的对象就会被垃圾收集器回收。一般回收算法也有如下几种:
1.标记-清除(Mark-sweep)
算法和名字一样,分为两个阶段:标记和清除。标记所有需要回收的对象,然后统一回收。这是最基础的算法,后续的收集算法都是基于这个算法扩展的。
不足:效率低;标记清除之后会产生大量碎片。效果图如下:
2.复制(Copying)
此算法把内存空间划为两个相等的区域,每次只使用其中一个区域。垃圾回收时,遍历当前使用区域,把正在使用中的对象复制到另外一个区域中。此算法每次只处理正在使用中的对象,因此复制成本比较小,同时复制过去以后还能进行相应的内存整理,不会出现“碎片”问题。当然,此算法的缺点也是很明显的,就是需要两倍内存空间。效果图如下:
3.标记-整理(Mark-Compact)
此算法结合了“标记-清除”和“复制”两个算法的优点。也是分两阶段,第一阶段从根节点开始标记所有被引用对象,第二阶段遍历整个堆,把清除未标记对象并且把存活对象“压缩”到堆的其中一块,按顺序排放。此算法避免了“标记-清除”的碎片问题,同时也避免了“复制”算法的空间问题。效果图如下:
(1,2,3 图文摘自 http://pengjiaheng.iteye.com/blog/520228,感谢原作者。)
4.分代收集算法
这是当前商业虚拟机常用的垃圾收集算法。分代的垃圾回收策略,是基于这样一个事实:不同的对象的生命周期是不一样的。因此,不同生命周期的对象可以采取不同的收集方式,以便提高回收效率。
为什么要运用分代垃圾回收策略?在java程序运行的过程中,会产生大量的对象,因每个对象所能承担的职责不同所具有的功能不同所以也有着不一样的生命周期,有的对象生命周期较长,比如Http请求中的Session对象,线程,Socket连接等;有的对象生命周期较短,比如String对象,由于其不变类的特性,有的在使用一次后即可回收。试想,在不进行对象存活时间区分的情况下,每次垃圾回收都是对整个堆空间进行回收,那么消耗的时间相对会很长,而且对于存活时间较长的对象进行的扫描工作等都是徒劳。因此就需要引入分治的思想,所谓分治的思想就是因地制宜,将对象进行代的划分,把不同生命周期的对象放在不同的代上使用不同的垃圾回收方式。
如何划分?将对象按其生命周期的不同划分成:年轻代(Young Generation)、年老代(Old Generation)、持久代(Permanent Generation)。其中持久代主要存放的是类信息,所以与java对象的回收关系不大,与回收息息相关的是年轻代和年老代。这里有个比喻很形象
“假设你是一个普通的 Java 对象,你出生在 Eden 区,在 Eden 区有许多和你差不多的小兄弟、小姐妹,可以把 Eden 区当成幼儿园,在这个幼儿园里大家玩了很长时间。Eden 区不能无休止地放你们在里面,所以当年纪稍大,你就要被送到学校去上学,这里假设从小学到高中都称为 Survivor 区。开始的时候你在 Survivor 区里面划分出来的的“From”区,读到高年级了,就进了 Survivor 区的“To”区,中间由于学习成绩不稳定,还经常来回折腾。直到你 18 岁的时候,高中毕业了,该去社会上闯闯了。于是你就去了年老代,年老代里面人也很多。在年老代里,你生活了 20 年 (每次 GC 加一岁),最后寿终正寝,被 GC 回收。有一点没有提,你在年老代遇到了一个同学,他的名字叫爱德华 (慕光之城里的帅哥吸血鬼),他以及他的家族永远不会死,那么他们就生活在永生代。”
笔记本识别不出来U盘的解决方法 [亲测有效]
转载连接https://jingyan.baidu.com/album/f96699bbfa1491894e3c1bc3.html?picindex=4 第一步 首先确认是不是U盘损坏了,可以把U盘插到其他电脑上去,看看能否读出。如果仍然都不出再进行下一步。
第二步 然后点击笔记本右下角的状态栏部分,看看有没有类似一个小U盘的标志。
第三步 然后点击这个U盘图标,查看并记下“弹出”下面的名字
第四步 第四步右键点击桌面的计算机/电脑,打开 管理,找到设备管理器,打开如下界面。
第五步 第五步一次点击右侧的各种驱动器、控制器、设备,查找是否有第三步的所记下的那个名字。着重找一下便携设备、磁盘驱动器、存储控制器、键盘等,因为有可能你的U盘被识别成了其他设备。
第六步 找到之后,右键点击卸载,然后拔下U盘重新插一次就可以了。
第七步 最后说两句,U盘读不出来的原因有很多,如果解决不了建议再试试其他方法。
整形数据 分类类型字节数取值范围有符号整型Shortint1-128~127Smallint2-32768~32767Integer4-2(31) ~2(31)-1Int648-2(63) ~2(63)-1无符号整型Byte10~255Word2 0~65535
LongWord40~ 2(32)-1浮点Single4字节浮点数精度8位 Real,Double8字节浮点数精度16位 2.字符型数据
1、字符型
char 、widechar (一个16位的Unicode字符)
表示一般为 'A' , 'a' , #65 , 'A' 2、字符串型
类型名称最大长度短字符型shortstring255个字符长字符型ansistring2(31)个字符宽字符型widestring2(30)个字符字符串型string2(31)个字符 3、布尔型数据
True 1 ,false 0
4、常量和变量
const
pi = 3.14159; //常量定义
alph = pi/3; //pi此前已经定义过,可以直接使用
enterchar:char=#13; //定义常量并定义类型
pi2:real = 3.1416
xingming:string[8]='zhangsan';
1.变量
var <变量名 >:<变量类型>
var <变量名>,<变量名> : <变量类型>
type
month=1..12;
x,y,z:real;
ch:char;
m1,m2:month;
days:array[1..12] of integer;
注意:
var 定义后 在定义const 后面不能跟var定义如:
a:integer;
const b:integer = 1;
Hive:
Hive不支持更改数据的操作,Hive基于数据仓库,提供静态数据的动态查询。其使用类SQL语言,底层经过编译转为MapReduce程序,在Hadoop上运行,数据存储在HDFS上。
HDFS:
HDFS是GFS的一种实现,他的完整名字是分布式文件系统,类似于FAT32,NTFS,是一种文件格式,是底层的。
Hive与Hbase的数据一般都存储在HDFS上。Hadoop HDFS为他们提供了高可靠性的底层存储支持。
Hbase:
Hbase是Hadoop database,即Hadoop数据库。它是一个适合于非结构化数据存储的数据库,HBase基于列的而不是基于行的模式。
HBase是Google Bigtable的开源实现,类似Google Bigtable利用GFS作为其文件存储系统,HBase利用Hadoop HDFS作为其文件存储系统;Google运行MapReduce来处理Bigtable中的海量数据,HBase同样利用Hadoop MapReduce来处理HBase中的海量数据。
Hadoop HDFS为HBase提供了高可靠性的底层存储支持,Hadoop MapReduce为HBase提供了高性能的计算能力,Zookeeper为HBase提供了稳定服务和failover机制。Pig和Hive还为HBase提供了高层语言支持,使得在HBase上进行数据统计处理变的非常简单。 Sqoop则为HBase提供了方便的RDBMS(关系型数据库)数据导入功能,使得传统数据库数据向HBase中迁移变的非常方便。
Pig:
Pig的语言层包括一个叫做PigLatin的文本语言,Pig Latin是面向数据流的编程方式。Pig和Hive类似更侧重于数据的查询和分析,底层都是转化成MapReduce程序运行。
区别是Hive是类SQL的查询语言,要求数据存储于表中,而Pig是面向数据流的一个程序语言。
Sqoop: Sqoop则为HBase提供了方便的RDBMS数据导入功能,使得传统数据库数据向HBase中迁移变的非常方便。
1:需求 项目需要搬迁到linux(centos7)上,于是趁这个机会玩一玩linux,发现刚开始的确不太容易玩的来 (/= _ =)/~┴┴
废话不多说下面就是步骤;
本地是用windows系统,用finalshell远程连接linux,
2:步骤 Node 1)先去官网下载一个node的压缩包(最好选源码文件)https://nodejs.org/en/download/, 或者去https://nodejs.org/dist/下载你需要的版本
这里我选的是 node-v10.5.0-linux-x64.tar.gz
2)将压缩包上传到服务器(这个不会的另行百度吧,推荐filezilla)
之后可以在上传的目录下看到文件
3)解压到指定目录(我这里是解压到nodejs这个目录)
tar -xvf node-v10.5.0-linux-x64.tar.gz
解压完成可以看到在nodejs/bin目录下有三个文件则解压所需文件成功
4)建立软链接
以上解压后还不是全局的,需要添加软链接
在根目录(重要)下进行一下命令(/nodejs/nodejs/bin/这是我放node,npm的路径)
ln -s /nodejs/nodejs/bin/node /usr/local/bin/
ln -s /nodejs/nodejs/bin/npm /usr/local/bin/
之后就可以在/usr/local/bin/下看到 node和npm
5)配置环境变量
如果以上步骤输入node -v会报错,此时就需要配置node的环境变量
在根目录下输入命令#vi /etc/profile
打开profile文件在末尾添加
export NODE_HOME=/usr/local(/usr/local:是建立软连接的上一个目录)
export PATH=$NODE_HOME/bin:$PATH
之后reboot重启输入看版本的命令就可以看到版本了
6)运行node
cd到项目目录,node server.js就可以了
Vue 1)下载vue,vue-cli3
在根目录下载
npm install -g vue
npm install -g @vue/cli
2)建立软连接
ln -s /nodejs/node/bin/vue /usr/local/bin/
3)查看版本
**)如果npm run serve启动不了项目可以先把之前的node_modules文件夹移除,再npm install
3:防火墙设置 linux默认只开启22端口,所以要向外部访问就得开启防火墙上对应端口访问设置
下面是我刚转专业到计算机专业的时候学的图,现在看看当时的我真傻逼。
其实判断是否为割点只需要看删除该点后整个图还是不是联通图,一共分为两步
①、删除指定的点,(在邻接矩阵中该点的行和列全部置0就好了,推荐使用 fill() )
②、DFS遍历图看看有几个联通分量。
下面的不要看了,我不删了它只是留个纪念
割点什么是割点呢;就是在一个连通图中删除一个点就导致整个图不连通了,那么这个点就叫做割点;DFS搜索树,我们可以发现有两类节点可以成为割点:
1、对根节点u,若其有两棵或两棵以上的子树,则该根结点u为割点;
2、对非叶子节点u(非根节点),若其子树的节点均没有指向u的祖先节点的回边,说明删除u之后,根结点与u的子树的节点不再连通;则节点u为割点。
我们用dfn[u]记录节点u在DFS过程中被遍历到的次序号,low[u]记录节点u或u的子树通过非父子边追溯到最早的祖先节点(即DFS次序号最小),这里的dfn low 跟上面的功能是一样的。,那么low[u]的计算过程如下:
#include<bits/stdc++.h> #define VertexNum 1000 #define MinNum 0 using namespace std; int n,m,Graph[VertexNum][VertexNum]; //n表示图对应有n个节点,m表示有m条边 int num[VertexNum],low[VertexNum],flag[VertexNum]={0},index=0; int x,y;//表示输入的边的邻接点 int X,Y; int dfs(int cur,int fat) { int child=0; //用来记录当前节点的子节点个数 index++; num[cur] = index; //表示当前(cur)节点的dfs访问顺序是第index low[cur] = index; //当前顶点能够访问到的最早的顺序序号,一开始就是自身。 for(int i=1;i<=n;i++) //开始循环遍历其他节点 { if(Graph[cur][i]==1) //与cur存在连接的节点进入判断语句。 { if(num[i]==0) //没有被访问的节点 { child++; //孩子数加一,多个循环,child 数就表示cur的子森林数 dfs(i,cur); //继续进一步dfs low[cur] = low[cur]>low[i]?low[i]:low[cur]; if(cur!=1 && low[i]>=num[cur]) //low[i]>=num[cur]的含义:以节点v为根的子树所能追溯到最早的祖先节点要么为i要么为cur。 flag[cur] = 1; //将cur标记为断点 if(cur==1&&child>=2) //若根有两个子森林 flag[cur] = 1; //将cur标记为断点 } else if(i!
有两种
一种是 使用router-link 这种直接可以用router-link-active 来写高亮样式 组件在路由跳转后 高亮依旧存在
一种是:is的应用了 点击触发事件 事件改变currentView的值 可以直接改掉 :is 这个引入文件入口
<template> <div class="index"> <div class="headTop"></div> <div class="nav"> <img src="../assets/img/logo.png" alt=""> <el-row :gutter="20"> <el-col :span="3" @click.native="tabChange('FirstScreen')" ><div class="grid-content bg-purple">首页</div></el-col> <el-col :span="3" @click.native="tabChange('pagetwo')"><div class="grid-content bg-purple">场站</div></el-col> <el-col :span="3" @click.native="tabChange('pagethree')" ><div class="grid-content bg-purple">订舱</div></el-col> </el-row> </div> <div :is="currentView"></div> <!-- <div class="aaa" >asdasd</div> --> </div> </template> <script> import FirstScreen from '../views/containers/FirstScreen' import pagetwo from '../views/containers/pagetwo' import pagethree from '../views/containers/pagethree' export default { name: 'index', components:{ FirstScreen, pagetwo, pagethree }, data () { return { FirstScreen: 'FirstScreen', pagetwo: 'pagetwo', pagethree: 'pagethree', currentView: 'FirstScreen',//组建切换 activeIndex: '1', activeIndex2: '1', } }, computed:{ }, created(){ }, methods:{ tabChange(tabItem) { this.
目录
载入数据
参数设置
训练模型
交叉验证
Early Stop
预测
GOSS
EFB
light GBM是微软开源的一种使用基于树的学习算法的梯度提升框架。
文档地址:官方文档
源码地址:github
中文文档地址:中文文档
论文地址:lightgbm-a-highly-efficient-gradient-boosting-decision-tree
参考博客:lightgbm,xgboost,gbdt的区别与联系 - Mata - 博客园 LightGBM原理之论文详解 - u010242233的博客 - CSDN博客
载入数据 LGB可以load以下类型数据。
libsvm/tsv/csv/txt format fileNumPy 2D array(s), pandas DataFrame, H2O DataTable’s Frame, SciPy sparse matrixLightGBM binary file load libsvm text file or a LightGBM binary file
train_data = lgb.Dataset('train.svm.bin') load a numpy array
data = np.random.rand(500, 10) # 500 entities, each contains 10 features label = np.
Microsoft Windows [版本 10.0.17134.523] (c) 2018 Microsoft Corporation。保留所有权利。 C:\Users\董丽萍>mvn --version Apache Maven 3.0.5 (r01de14724cdef164cd33c7c8c2fe155faf9602da; 2013-02-19 21:51:28+0800) Maven home: E:\Tool\apache-maven-3.0.5\bin\.. Java version: 1.8.0_152, vendor: Oracle Corporation Java home: C:\Program Files\Java\jdk1.8.0_152\jre Default locale: zh_CN, platform encoding: GBK OS name: "windows 10", version: "10.0", arch: "amd64", family: "dos" C:\Users\董丽萍>cd F:\工单\RM-TC20181213568运管-风控查询优化及金额冻结需求\代码\备份\BOMS\Code C:\Users\董丽萍>f:/ 'f:/' 不是内部或外部命令,也不是可运行的程序 或批处理文件。 C:\Users\董丽萍>f 'f' 不是内部或外部命令,也不是可运行的程序 或批处理文件。 C:\Users\董丽萍>f: F:\工单\RM-TC20181213568运管-风控查询优化及金额冻结需求\代码\备份\BOMS\Code>dir 驱动器 F 中的卷是 新加卷 卷的序列号是 4836-C878 F:\工单\RM-TC20181213568运管-风控查询优化及金额冻结需求\代码\备份\BOMS\Code 的目录 2019/01/30 11:39 <DIR> . 2019/01/30 11:39 <DIR> .
一.准备环境
(1) java 11+ (本人使用的java12)
具体安装内容和步骤,参考:https://blog.csdn.net/sweet__queen/article/details/88680113
(2).gradle 5.1+ (gradle 5.2)
具体安装内容和环境变量配置,参考:https://blog.csdn.net/sweet__queen/article/details/88680723
(3).elasticsearch6.6.1版本源码
源码下载参考地址:https://download.csdn.net/download/sweet__queen/11041049
(4).idea (2018)
二.开始部署
(1) 进入elasticsearch6.6.1源码主目录下,打开cmd,执行gradle idea,开始漫长的build过程~