poj 1061 青蛙的约会+拓展欧几里得+题解

青蛙的约会+拓展欧几里得+题解 纵有疾风起 题意 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面。它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止。可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置。不过青蛙们都是很乐观的,它们觉得只要一直朝着某个方向跳下去,总能碰到对方的。但是除非这两只青蛙在同一时间跳到同一点上,不然是永远都不可能碰面的。为了帮助这两只乐观的青蛙,你被要求写一个程序来判断这两只青蛙是否能够碰面,会在什么时候碰面。 我们把这两只青蛙分别叫做青蛙A和青蛙B,并且规定纬度线上东经0度处为原点,由东往西为正方向,单位长度1米,这样我们就得到了一条首尾相接的数轴。设青蛙A的出发点坐标是x,青蛙B的出发点坐标是y。青蛙A一次能跳m米,青蛙B一次能跳n米,两只青蛙跳一次所花费的时间相同。纬度线总长L米。现在要你求出它们跳了几次以后才会碰面。 输入 输入只包括一行5个整数x,y,m,n,L,其中x≠y < 2000000000,0 < m、n < 2000000000,0 < L < 2100000000。 输出 输出碰面所需要的跳跃次数,如果永远不可能碰面则输出一行"Impossible" 前话-拓展欧几里得(下方高能!!!) 扩展欧几里德算法是用来在已知a, b求解一组整数解x,y,使它们满足贝祖等式(具体不是很清楚是啥意思,反正就那样): \(ax+by = gcd(a, b) =d\)(解一定存在,根据数论中的相关定理)。扩展欧几里德常用在求解模线性方程及方程组中。 对于普通的公式\(ax+by = c\)有整数解的条件是\(c=k*gcd(a, b)\),k为任意常数。 对于公式\(ax+by = gcd(a, b) =d\),求解其中一个x,y的方法及其证明 显然当 \(b=0,gcd(a,b)=a\)时,此时 \(x=1, y=0\); \(a>b>0\) 时,设 \(ax_1+ by_1= gcd(a,b)\); \(bx_2+ (a\ mod\ b)*y_2= gcd(b,\ a\ mod\ b)\); 根据朴素的欧几里德原理有 \(gcd(a,b) = gcd(b,a\ mod\ b)\); 则:\(ax_1+ by_1= bx_2+ (a\ mod\ b)y_2\); 即:\(ax_1+ by_1= bx_2+ (a - [a / b] * b)y_2=ay_2+ bx_2- [a / b] * by_2\)。

k8s miniKube 入门

k8s miniKube 入门 miniKube 是单机版kubernetes, 可以配置运行在同一台主机上的服务和pod,并使用docker作为虚拟化工具 下载:直接下载可执行文件,复制到path 路径,免安装。 启动:minikube 支持多种虚拟化工具,如:virtualbox, 不过在linux里可以支持docker minikube start --vm-driver=none 等待一会最终输出 * Done! kubectl is now configured to use "minikube" 由于需要下载很多支持的东西,经常失败,最好添加74.125.204.82 k8s.gcr.io 到hosts文件。 然后创建一个Deployment kubectl run hello-minikube --image=k8s.gcr.io/echoserver:1.10 --port=8080 这个镜像下载比较慢,可以下载阿里的registry.cn-qingdao.aliyuncs.com/k8slast/echoserver 即 kubectl run hello-minikube --image=registry.cn-qingdao.aliyuncs.com/k8slast/echoserver --port=8080 输出:deployment.apps/hello-minikube created 再将deployment 暴露成服务 kubectl expose deployment hello-minikube --type=NodePort 输出:service/hello-minikube exposed 最后获取访问url minikube service hello-minikube --url 输出访问url:http:://xxxxx:port 通过url可以访问服务资源 删除服务资源 先删除服务: minikube delete service hello-minikube再删除deployment: minikube delete deployment hello-minikube最后删除minikube集群 minikube stop && minikube delete 一个简单的演示完成

使用java将word文档docx,doc(包含图形,文本框)完美转换成所有格式图片(pdf,png,gif,jpeg等等)

使用java将word文档docx,doc(包含图形,文本框,图片等)完美转换成所有格式图片(pdf,png,gif,jpeg等等)下文中附带代码,效果图等 思路使用到的包实现代码效果图: 思路 使用jacob将docx转换成doc,用openoffice将doc转成pdf,最后是用pdfbox将pdf转成任意格式图片 使用到的包 https://download.csdn.net/download/weixin_44396516/11393966 实现代码 把上面的包下载并导入,代码中有些内容自行修改,有问题请留言,看到会回复。 import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.ConnectException; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Properties; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.encryption.InvalidPasswordException; import org.apache.pdfbox.rendering.ImageType; import org.apache.pdfbox.rendering.PDFRenderer; import org.apache.pdfbox.tools.imageio.ImageIOUtil; import org.apache.poi.hwpf.HWPFDocument; import org.apache.poi.hwpf.converter.PicturesManager; import org.apache.poi.hwpf.converter.WordToHtmlConverter; import org.apache.poi.hwpf.model.PAPX; import org.apache.poi.hwpf.usermodel.PictureType; import org.apache.poi.xwpf.converter.core.BasicURIResolver; import org.

Invalid configuration for cluster creation.Redis Cluster requires at least 3 master nodes.

前提: 跟着网上的教程创建好6个进程分别是7001-7006,并且安装好高版本的ruby。创建集群时输入如下命令: ./bin/redis-trib.rb create --replicas 192.168.132.100:7001 192.168.132.100:7002 192.168.132.100:7003 192.168.132.100:7004 192.168.132.100:7005 192.168.132.100:7006 报错: *** ERROR: Invalid configuration for cluster creation. *** Redis Cluster requires at least 3 master nodes. *** This is not possible with 5 nodes and 192 replicas per node. *** At least 579 nodes are required. 错误原因 1、replicas和参数都没有加,当前所有结点默认都是master结点 ,结点数不足报错。 2、只加了replicas没加参数,当前所有结点默认都是master结点,结点数不足报错。 错误解析: 错误说当前集群创建是无效的。Redis集群创建时需要至少3个主节点。对于每个节点有5个节点和192个副本,这是不可能的。至少需要579个节点。原来 replicas后面是要加一个数字作为参数,表示一个主结点几个从结点,例如我当前是总共6个节点,3个主节点,剩下的3个都是从结点,所以我只能每个主结点分配一个从结点,所以参数的值为1,当然假如我总结点数有9个结点也可是每个主节点分配2个从结点。replicas的作用让redis自动地分配主从。 正确姿势: ./bin/redis-trib.rb create --replicas 1 192.168.132.100:7001 192.168.132.100:7002 192.168.132.100:7003 192.168.132.100:7004 192.168.132.100:7005 192.168.132.100:7006 结果: >>> Creating cluster >>> Performing hash slots allocation on 6 nodes.

更换Centos系统的镜像源

1. 备份本地yum源 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo_bak 2.获取阿里yum源配置文件 wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo 3.更新cache yum makecache 4.查看 yum -y update 下面提供一些其他的镜像源: 阿里云开源镜像:http://mirrors.aliyun.com/ 网易开源镜像:http://mirrors.163.com/ 清华大学开源镜像:https://mirror.tuna.tsinghua.edu.cn/

GVim配置一个漂亮的NerdTree

GVim配置一个漂亮的NerdTree GVim使用也有一段时间了,有空写几个简单的教程帮助新手快速上手,定制一个个性化的编辑器把。以下是我的NerdTree效果展示。 NerdTree插件 NerdTree下载安装 如果你安装了插件管理器的化安装就很简单了,如果没有安装使用任何插件管理器,那我建议你还是装一个,因为vim你会用到的插件挺多的,有个管理器很方便。 将这句添加到vimrc中Plugin 'scrooloose/nerdtree',随后重启下vim然后命令模式下执行:BundleInstall(具体根据你装的插件,我装的是Bundle。)安装指令,完毕后最好再重启一次vim。 NerdTree配置 ps: 以下我的配置仅供参考,具体配置请查阅github上的文档,因为随着作者版本的升级指令和功能可能会边。总之请灵活学习。 """"""""""""""""""""""""""""""" "NerdTree setting """"""""""""""""""""""""""""""" set encoding=utf-8 set termencoding=utf-8 set fileencoding=chinese set fileencodings=ucs-bom,utf-8,chinese set langmenu=zh_CN.utf-8 language messages zh_cn.utf-8 "Show line number. let g:NERDTreeShowlineNumber=1 "Show hide file. let g:NERDTreeHidden=0 "Show Node model. let NERDTreeDirArrows=1 "Delete help information at the top let NERDTreeMinimalUI=1 let g:NERDTreeDirArrowExpandable = '|' let g:NERDTreeDirArrowCollapsible = '/' 简单解释下,前面几行将几个部分的字体设置为utf-8是为了防止再windows下乱码。是否显示行号这里配置为是,因为否的话左边一列每行首都会显示|符号,太多了不好看。配置为是反倒不会显示行号,且只有在文件夹左边才会显示|符号。剩下的配置根据注释意思好理解。文件召开或关闭很多人配置为三角符号,我试了下windows下需要折腾合适字体才能显示,我现在用的molokai字体是不支持的。其实我更喜欢的是键盘上的|和/符号,简单粗暴。 另外我还建议加上这样一句配置,作用是当剩余的窗口都不是文件编辑窗口时,自动退出vim。就是你都不编辑文件了,还剩个NerdTree窗口在那里时自动退出GVim(执行:qa!)。 autocmd BufEnter * if 0 == len(filter(range(1, winnr('$')), 'empty(getbufvar(winbufnr(v:val), "

关于啊哈!算法的阅后总结(1)

作为入门算法书,从各种实战的算法列举起,是一本既基础又实用的算法书籍,这里我截取几个重要的算法内容进行总结,作为这一阶段的回顾。 排序类:快速排序 在本文中作者基于快速排序思想给出了一种变式快排的形式,这里记录一下两者的区别。 1.实际的快排:快排总的来说是基准数的交换,即选取几个处于头部的基准数和两个探测哨兵,从队列的两端向内遍历,记录为a[0]、i和j。遍历的过程中,若发现j<a[0],则j与a[0]交换位置,若发现i>a[0],则i与a[0](已与j交换位置的a[0])交换位置,重复这个过程直到i==j。 2.啊哈算法里的快排:作者选取基准数在遍历过程中不变,只让i和j进行交换,最后a[0]再与i(j)进行交换,实际上这还是快排的思想,只是基准数我们放到最后进行交换罢了。 举例:有队列“6 1 2 7 9 3 4 5 10 8” 首先哨兵j开始出动。因为此处设置的基准数是最左边的数,所以需要让哨兵j先出动。哨兵j一步一步地向左挪动(即j--),直到找到一个小于6的数停下来。接下来哨兵i再一步一步向右挪动(即i++),直到找到一个数大于6的数停下来。最后哨兵j停在了数字5面前,哨兵i停在了数字7面前。 现在交换哨兵i和哨兵j所指向的元素的值。交换之后的序列如下。 6 1 2 5 9 3 4 7 10 8 到此,第一次交换结束。接下来开始哨兵j继续向左挪动。发现了4(比基准数6要小,满足要求)之后停了下来。哨兵i也继续向右挪动的,他发现了9(比基准数6要大,满足要求)之后停了下来。此时再次进行交换,交换之后的序列如下。 6 1 2 5 4 3 9 7 10 8 第二次交换结束,“探测”继续。哨兵j继续向左挪动,他发现了3(比基准数6要小,满足要求)之后又停了下来。哨兵i继续向右移动,糟啦!此时哨兵i和哨兵j相遇了,哨兵i和哨兵j都走到3面前。说明此时“探测”结束。我们将基准数6和3进行交换。交换之后的序列如下。 3 1 2 5 4 6 9 7 10 8 至此,我们将基准数6找到了,之后采用二分与递归的办法将 3 1 2 5 4 和 9 7 10 8进行又一轮递归。 代码如下: #include <stdio.h> /*unsigned int partion(unsigned int R[] , unsigned int low ,unsigned int high) { unsigned int swap,base; swap=R[low];base=R[low]; while(low<high) { while(R[high]>=base&&low<high) high--; R[low]=R[high]; while(R[low]<=base&&low<high) low++; R[high]=base;swap=R[low]; R[low]=R[high];R[high]=swap; } return low; } void quick_sort(unsigned int ISBN[] ,unsigned int low ,unsigned int high) { unsigned int position; if(low<high) { position=partion(ISBN , low , high); quick_sort(ISBN , low , position-1); quick_sort(ISBN , position+1 , high); } } int main() { unsigned int ISBN[10]={20,40,32,67,40,20,89,300,400,15},low=0,high=9; quick_sort(ISBN,low,high); for(low=0;low<=high;low++) printf("

国际会议poster: 海报制作流程 & 格式介绍

1 流程 word制作, 转pdf, 打印 2 模板 UCL https://wenku.baidu.com/view/034bcb7e4a7302768f99392a.html 3 CYBER2019格式要求 海报尺寸: A1尺寸 23.4英寸(59.4厘米)宽,33.1英寸(84.1厘米)高。 请注意,以A4尺寸列印已递交的整张纸作为海报是不可接受的。 标题:海报的标题应出现在顶部,字体大小至少为42 pt)。在标题下面,写上作者和他们的名字 标题在顶部 字体42 文本:文本应该在五英尺外就能读懂。使用最小字体大小为17 pt。 保持文本简短。试着用文字来介绍这项研究,解释视觉效果,并引导观众注意视觉效果中所描绘的重要数据趋势和关系,陈述并解释从数据中得出的解释。把未来的研究计划或问题放在简历中与读者讨论也是一个好主意 图:每个图应该有一个简短的标题。数字应该按照第一次提到的顺序连续编号,尽量使用彩色数字,而不是只使用黑白文本,以使您的海报具有吸引力,并突出您的论文的重要技术内容。确保文本和视觉效果是统一的。 海报显示 作者应张贴您的海报张贴面板上的一天上午,在您的海报会话。海报编排的详细时间表请参阅节目编排网页。当你抵达会场时,请与秘书处职员联络: 报告的存在, 确认指定的董事会编号, 把塑料 请注意你的海报应该提前做好准备。会议的最后一分钟准备工作将没有时间和材料。我们将提供塑料胶带将您的海报贴在展板上。 请在当天结束前将海报取下,否则将被丢弃。

Logstash jdbc插件实现数据增量更新

Logstash jdbc插件实现数据增量更新 上节我们看了如何抽取关系型数据库数据至elasticsearch,但实际中我们需要实现增量更新,本文讨论如何实现增量更新。 更新elasticsearch数据 确保elasticsearch中数据为最新的,即原数据表数据更新后推送至elasticsearch中。一般有两种方法: 定时运行相同的logstash配置文件,则会一遍一遍发送数据————包括已改变的数据和未改变的数据。仅发送表中已改变的数据。 下面我们分别探讨这两种方法,逐步掌握一些关键配置,最终实现数据高效地增量更新。 第一种方法——全量更新 第一种方法,配置文件大致如下: input { jdbc { jdbc_driver_library => "config.d/ojdbc5.jar" jdbc_driver_class => "Java::oracle.jdbc.driver.OracleDriver" jdbc_connection_string => "jdbc:oracle:thin:@192.168.0.192:1521:orcl" jdbc_user => "testuser" jdbc_password => "yourpassword" jdbc_paging_enabled => "true" statement => "select comp_name,comp_type,unified_code,id as person_id from leg_info" schedule => "0 5 * * * *" } } output { elasticsearch { index => "leg_base_info" document_id=> "%{person_id}" hosts => ["http://localhost:9200"] } } 使用’schedule’选项实现周期运行。这里指定每5分钟运行一次。你可以根据业务需要进行定义,语法可以参考cron教程。 那为什么要指定document_id选项呢? 在elasticsearch中,每个文档都会创建唯一ID,用于标识该文档。因为需要反复运行logstash配置文件,会重复创建相同的文档。通过使用document_id字段可以避免创建重复文档。这里我们告诉插件使用表的主键(id字段)作为文档ID。这样elasticsearch就不会对相同记录创建多个文档,已存在的文档会被覆盖。elasticsearch会保存新增的记录和更新的记录。 第二种方法——增量更新 为了在elasticsearch中实现增量更新,则需要数据库中有一列用作参考,示例表中有update_date字段表示该行数据最后更新时间。下面使用该列,配置文件如下: input { jdbc { jdbc_driver_library => "

GC算法 (标记清除、复制、标记整理、 分代收集) 、 新生代 老年代

一、标记-清除算法(Mark-Sweep) 1标记阶段:首先通过根节点,标记所有从根节点开始的可达对象。未被标记的对象就是未被引用的垃圾对象 2清除阶段:清除所有未被标记的对象。 不足:1效率问题:标记和清除两个过程的效率都不高。 2空间问题:标记清除后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要 分配较大对象时,无法找到足够的连续内存而不得不提前出发另一次垃圾收集动作。 标记-清除算法是现代垃圾回收算法的思想基础。 二、复制算法(Copying) 1将原有的内存空间分为两块,每次只使用一块, 2在垃圾回收时,将正在使用的内存中的存活对象复制到未被使用的内存块中,然后清除正在使用的内存块中的所有对象。 3交换两个内存的角色,完成垃圾回收。 与标记-清除算法相比,复制算法是一种相对高效的回收方法。 不适用于存活对象较多的场合,如老年代。 三、标记—整理算法(Mark-Compact) 1标记阶段:先通过根节点,标记所有从根节点开始的可达对象,未被标记的为垃圾对象 2整理阶段:将所有的存活对象压缩到内存的一段,之后清理边界外所有的空间 标记-压缩算法 适合用于存活对象较多的场合,如老年代。 它在标记-清除算法的基础上做了一些优化。和标记-清除算法一样,标记-压缩算法也首先需要从根节点开始,对所有可达对象做一次标记。但之后,它并不简单的清理未标记的对象,而是将所有的存活对象压缩到内存的一端。之后,清理边界外所有的空间。 标记压缩对标记清除而言,有什么优势呢? 三种算法的比较: 效率: 复制 > 标记整理 > 标记清除 (此处的效率只是简单的对比时间复杂度,实际情况不一定如此) 内存利用率: 标记整理 > 标记清除 > 复制 内存整齐度: 复制 = 标记整理 > 标记清除 四、分代收集算法(Generational Collection) 当前商业虚拟机的垃圾收集都采用“分代收集算法”, 这种算法并没有什么新的思想,只是根据对象存活周期的不同将内存划分为几块。 一般是将Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。 在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用“复制算法”,只需要付出少量存活对象的复制成本就可以完成收集。 在老年代中,因为对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记-清理”或“标记-整理”算法来进行回收。 五、新生代 与 老年代 Java堆是JVM管理的最大一块内存空间,主要存放对象实例。 堆被分为两块区域:新生代 young、 老年代old 堆大小=新生代+老年代 (新生代占堆空间的1/3、老年代占堆空间2/3) 新生代又被分为了eden、from survivor、to survivor(8:1:1) 新生代这样划分是为了更好的管理堆内存中的对象,方便GC算法---复制算法来进行垃圾回收。 JVM每次只会使用eden和其中一块survivor来为对象服务,所以无论什么时候,都会有一块survivor空间,因此新生代实际可用空间只有90%。 新生代GC(minor gc)----------指发生在新生代的垃圾回收动作,因为JAVA对象大多数都是朝生夕死的特性,所以minor gc非常平凡,使用复制算法快速的回收。 新生代几乎是所有JAVA对象出生的地方,JAVA对象申请的内存和存放都是在这个地方。 当对象在eden(其中包括一个survivor,假如是from),当此对象经过一次minor gc后仍然存活,并且能够被另外一块survivor所容纳(这里survivor则是to了),则使用复制算法将这些仍然存活的对象复制到to survior区域中,然后清理掉eden和from survivor区域,并将这些存活的对象年龄+1,以后对象在survivor中每熬过一次gc则增加1,当年龄达到某个值时(默认15,通过设置参数-xx:maxtenuringThreshold来设置),这些对象就会成为老年代。但是也不一定,当一些较大的对象(需要分配连续的内存空间)则直接进入老年代。

HC32F003系列芯片时钟源性能测试及分析

HC32F003系列芯片时钟源性能测试及分析 测试概要 测试目的:分析HC32F003系列芯片几种时钟源的性能差异。主要分析频率、占空比的误差范围。测试项目:分别测试以下几种时钟源的性能,每种测试不少于10次。 内部高速4MHz内部高速8MHz内部高速16MHz内部高速22.12MHz内部高速24MHz内部低速32.8KHz内部低速38.4KHz外部高速32MHz 测试环境及工具: 环境:室内,温度和电压均稳定(内部晶振易受电压和温度波动影响)。工具:HC32F005C6、200M数字示波器(200M精度较差)。 测试人员:Calm测试时间:2019-07-18 测试结论 测试项频率波动范围平均频率平均正占空比频率平均偏差正占空比平均偏差ppm内部高速4MHz(理论频率4000000Hz)3.97~3.98MHz3.97MHz50.449%-0.03MHz+0.449%7500内部高速8MHz(理论频率8000000Hz)8.13~8.16MHz8.139MHz58.531%+0.139MHz+8.531%17375内部高速16MHz(理论频率16000000Hz)15.97~16.04MHz16.004MHz55.015%+0.004MHz+5.015%250内部高速22.12MHz(理论频率22120000Hz)21.83~21.93MHz21.90MHz48.213%-0.22MHz-1.787%9945.75内部高速24MHz(理论频率24000000Hz)23.65~23.90MHz23.861MHz47.393%-0.139MHz-2.607%5791.67内部低速32kHz(理论频率32768Hz)32.56~32.70kHz32.645kHz55.275%-0.123kHz-5.275%3753.66内部低速38kHz(理论频率38400Hz)38.36~38.47kHz38.433kHz55.583%+0.033kHz+5.583%859.375外部低速32MHz(理论频率32000000Hz)31.97~32.00MHz31.997MHz58.059%-0.001MHz+8.059%31.25 结论:内部高速、内部低俗、外部高速三种时钟源中频率误差最小的是外部32MHz(ppm仅为31.25),相对而言内部时钟频率误差较大。内部高速时钟频率精度最高的是16MHz(ppm为250),精度最低的是内部8M(ppm为17375)。内部低速精度更好的是38k。以上测试是在电压和温度(室温)稳定的情况下。 测试数据 内部高速4MHz(理论频率4000000Hz) 测试结论统计 测试组号频率正占空比频率偏差正占空比偏差13.97MHz50.79%-0.03MHz+0.79%23.97MHz50.44%-0.03MHz+0.44%33.97MHz49.96%-0.03MHz-0.04%43.97MHz50.44%-0.03MHz+0.44%53.98MHz50.52%-0.02MHz+0.52%63.97MHz50.40%-0.03MHz+0.40%73.97MHz50.75%-0.03MHz+0.75%83.97MHz50.00%-0.03MHz+0.00%93.97MHz50.75%-0.03MHz+0.75%103.97MHz50.44%-0.03MHz+0.44% 频率波动范围平均频率平均正占空比频率平均偏差正占空比平均偏差3.97~3.98MHz3.97MHz50.449%-0.03MHz+0.449% 测试组号:1 描述:频率=3.97MHz,正占空比50.79%。 结论:频率偏差-0.03MHz,占空比偏差+0.79%。 测试组号:2 描述:频率=3.97MHz,正占空比50.44%。 结论:频率偏差-0.03MHz,占空比偏差+0.44%。 测试组号:3 描述:频率=3.97MHz,正占空比49.96%。 结论:频率偏差-0.03MHz,占空比偏差-0.04%。 测试组号:4 描述:频率=3.97MHz,正占空比50.44%。 结论:频率偏差-0.03MHz,占空比偏差+0.44%。 测试组号:5 描述:频率=3.98MHz,正占空比50.52%。 结论:频率偏差-0.02MHz,占空比偏差+0.52%。 测试组号:6 描述:频率=3.97MHz,正占空比50.40%。 结论:频率偏差-0.03MHz,占空比偏差+0.40%。 测试组号:7 描述:频率=3.97MHz,正占空比50.75%。 结论:频率偏差-0.03MHz,占空比偏差+0.75%。 测试组号:8 描述:频率=3.97MHz,正占空比50.00%。 结论:频率偏差-0.03MHz,占空比偏差0.00%。 测试组号:9 描述:频率=3.97MHz,正占空比50.75%。 结论:频率偏差-0.03MHz,占空比偏差+0.75%。 测试组号:10 描述:频率=3.97MHz,正占空比50.44%。 结论:频率偏差-0.03MHz,占空比偏差+0.44%。 内部高速8MHz(理论频率8000000Hz) 测试结论统计 测试组号频率正占空比频率偏差正占空比偏差18.14MHz58.63%+0.14MHz+8.63%28.14MHz58.47%+0.14MHz+8.47%38.13MHz58.54%+0.13MHz+8.54%48.14MHz59.28%+0.14MHz+9.28%58.14MHz58.63%+0.14MHz+8.63%68.13MHz58.54%+0.13MHz+8.54%78.14MHz58.47%+0.14MHz+8.47%88.13MHz57.72%+0.13MHz+7.72%98.14MHz58.63%+0.14MHz+8.63%108.16MHz58.40%+0.16MHz+8.40% 频率波动范围平均频率平均正占空比频率平均偏差正占空比平均偏差8.13~8.16MHz8.139MHz58.531%+0.139MHz+8.531% 测试组号:1 描述:频率=8.14MHz,正占空比58.63%。 结论:频率偏差+0.14MHz,占空比偏差+8.63%。 测试组号:2 描述:频率=8.14MHz,正占空比58.47%。 结论:频率偏差+0.14MHz,占空比偏差+8.47%。 测试组号:3 描述:频率=8.13MHz,正占空比58.54%。 结论:频率偏差+0.13MHz,占空比偏差+8.54%。 测试组号:4 描述:频率=8.14MHz,正占空比59.28%。 结论:频率偏差+0.14MHz,占空比偏差+9.28%。 测试组号:5 描述:频率=8.14MHz,正占空比58.63%。 结论:频率偏差+0.14MHz,占空比偏差+8.63%。 测试组号:6 描述:频率=8.13MHz,正占空比58.54%。 结论:频率偏差+0.13MHz,占空比偏差+8.54%。 测试组号:7 描述:频率=8.14MHz,正占空比58.47%。

http转https,腾讯云服务器SSL证书安装指引

Nginx的产生 没有听过Nginx?那么一定听过它的"同行"Apache吧!Nginx同Apache一样都是一种WEB服务器。基于REST架构风格,以统一资源描述符(Uniform Resources Identifier)URI或者统一资源定位符(Uniform Resources Locator)URL作为沟通依据,通过HTTP协议提供各种网络服务。 简单说,你的腾讯云主机想成为能通过http请求到数据的服务器,就必须配置成WEB服务器,Nginx就是WEB服务器的其中一种类型。所以在实现http转https之前,你需要配置你的腾讯云服务器为Nginx服务器。 一、Linux 安装Nginx rpm 包方式(推荐) (1)进入下载页面,选择合适版本下载。 $ wget http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm (2)安装 nginx rpm 包 nginx rpm 包实际上安装的是 nginx 的 yum 源。 $ rpm -ivh nginx-*.rpm (3)正式安装 rpm 包 $ yum install nginx (4)关闭防火墙 $ firewall-cmd --zone=public --add-port=80/tcp --permanent $ firewall-cmd --reload (5) 启动 Nginx 安装成功后,直接执行 nginx 命令即可启动 nginx。 启动后,访问站点: Linux 开机自启动 Centos7 以上是用 Systemd 进行系统初始化的,Systemd 是 Linux 系统中最新的初始化系统(init),它主要的设计目标是克服 sysvinit 固有的缺点,提高系统的启动速度。Systemd 服务文件以 .service 结尾。 rpm 包方式 如果是通过 rpm 包安装的,会自动创建 nginx.

js代码实现录音上传

js代码实现录音上传 1.html页面2.Recorder.js内容3.flask写法 1.html页面 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title id="title"></title> </head> <body> <audio id="player" autoplay controls></audio> <p> <button onclick="start_reco()">开始录音</button> </p> <p> <button onclick="ai_reco()" style="background-color: cornflowerblue">发送语音指令</button> </p> </body> <script type="application/javascript" src="/static/jquery-3.3.1.min.js"></script> <script type="text/javascript" src="/static/Recorder.js"></script> <script type="application/javascript"> var reco = null; var audio_context = new AudioContext();//音频内容对象 navigator.getUserMedia = (navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia); // 兼容其他浏览器 navigator.getUserMedia({audio: true}, create_stream, function (err) { console.log(err) }); function create_stream(user_media) { var stream_input = audio_context.

springboot中@Value的工作原理

转截自:https://blog.csdn.net/gs_albb/article/details/85401720 我们知道springboot中的Bean组件的成员变量(属性)如果加上了@Value注解,可以从有效的配置属性资源中找到配置项进行绑定,那么这一切是怎么发生的呢?下文将简要分析一下@Value的工作原理。 springboot版本: springboot-2.0.6.RELEASE 概述 springboot启动过程中,有两个比较重要的过程,如下: 1 扫描,解析容器中的bean注册到beanFactory上去,就像是信息登记一样。 2 实例化、初始化这些扫描到的bean。 @Value的解析就是在第二个阶段。BeanPostProcessor定义了bean初始化前后用户可以对bean进行操作的接口方法,它的一个重要实现类AutowiredAnnotationBeanPostProcessor正如javadoc所说的那样,为bean中的@Autowired和@Value注解的注入功能提供支持。 解析流程 调用链时序图 @Value解析过程中的主要调用链,我用以下时序图来表示: 这里先简单介绍一下图上的几个类的作用。 AbstractAutowireCapableBeanFactory: 提供了bean创建,属性填充,自动装配,初始胡。支持自动装配构造函数,属性按名称和类型装配。实现了AutowireCapableBeanFactory接口定义的createBean方法。 AutowiredAnnotationBeanPostProcessor: 装配bean中使用注解标注的成员变量,setter方法, 任意的配置方法。比较典型的是@Autowired注解和@Value注解。 InjectionMetadata: 类的注入元数据,可能是类的方法或属性等,在AutowiredAnnotationBeanPostProcessor类中被使用。 AutowiredFieldElement: 是AutowiredAnnotationBeanPostProcessor的一个私有内部类,继承InjectionMetadata.InjectedElement,描述注解的字段。 StringValueResolver: 一个定义了处置字符串值的接口,只有一个接口方法resolveStringValue,可以用来解决占位符字符串。本文中的主要实现类在PropertySourcesPlaceholderConfigurer#processProperties方法中通过lamda表达式定义的。供ConfigurableBeanFactory类使用。 PropertySourcesPropertyResolver: 属性资源处理器,主要功能是获取PropertySources属性资源中的配置键值对。 PropertyPlaceholderHelper: 一个工具类,用来处理带有占位符的字符串。形如${name}的字符串在该工具类的帮助下,可以被用户提供的值所替代。替代途经可能通过Properties实例或者PlaceholderResolver(内部定义的接口)。 PropertyPlaceholderConfigurerResolver: 上一行所说的PlaceholderResolver接口的一个实现类,是PropertyPlaceholderConfigurer类的一个私有内部类。实现方法resolvePlaceholder中调用了外部类的resolvePlaceholder方法。 调用链说明 这里主要介绍一下调用链中的比较重要的方法。 AbstractAutowireCapableBeanFactory#populateBean方法用于填充bean属性,执行完后可获取属性装配后的bean。 protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) { ... if (hasInstAwareBpps) { // 遍历所有InstantiationAwareBeanPostProcessor实例设置属性字段值。 for (BeanPostProcessor bp : getBeanPostProcessors()) { // AutowiredAnnotationBeanPostProcessor会进入此分支 if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; pvs = ibp.

【MQ】消息中间件集群崩溃,如何保证百万生产数据不丢失?

“上一篇讲消息中间件的文章《扎心!线上服务宕机时,如何保证数据100%不丢失?》,初步给大家介绍了一个在生产环境中可能遇到的问题,就是你的消费者服务可能会宕机,一旦宕机,你就需要考虑是否会导致没处理完的消息丢失。 这篇文章,再给不太熟悉MQ技术的同学,介绍另外一个生产环境中可能会遇到的问题。 目前为止,你的RabbitMQ部署在线上服务器了,对吧?然后订单服务和仓储服务都可以基于RabbitMQ来收发消息,同时仓储服务宕机,不会导致消息丢失。 好,我们来看下目前为止的架构图。 那如果此时出现一个问题,就是说订单服务投递了订单消息到RabbitMQ里去,RabbitMQ暂时放在了自己的内存中,还没来得及投递给下游的仓储服务呢,此时RabbitMQ突然宕机了,会怎么样? 答案其实很简单,默认情况下,按照我们目前的代码和配置,这个数据就会丢失了。 所以在这里而言,就牵扯到了RabbitMQ的一个较为重要的概念:消息的持久化,用英文来说就是durable机制。 然后这里又有一个引申的概念,如果按照我们之前的代码和配置,默认情况下,RabbitMQ一旦宕机就再次重启,就会丢失我们之前创建的queue。所以首先得先让queue是持久化的。 使用下面的代码,就可以把我们的“warehouse_schedule_delivery”这个queue,也就是仓储调度发货的queue,设置为持久化的。 这样,即使RabbitMQ宕机后重启,也会恢复之前创建好的这个queue。 channel.queueDeclare("warehouse_schedule_delivery",true,false,false,null); 大家看到上面那行定义和创建queue的代码么?核心在于第二个参数,第二个参数是true。 他的意思就是说,这个创建的queue是durable的,也就是支持持久化的。 RabbitMQ会把这queue的相关信息持久化的存储到磁盘上去,这样RabbitMQ重启后,就可以恢复持久化的queue。 OK,现在你的queue的信息可以持久化了,RabbitMQ宕机重启后会自动恢复queue。但是,你的queue里的message数据呢? queue里都是订单服务发送过去的订单消息数据,如果RabbitMQ还没来得及投递queue里的订单消息到仓储服务,结果RabbitMQ就宕机了。 那此时RabbitMQ重启之后,他可以恢复queue的信息,但是queue的message数据是没法恢复了。 所以此时还有一个重要的点,就是在你的订单服务发送消息到RabbitMQ的时候,需要定义这条消息也是durable,即持久化的。 channel.basicPublish("", "warehouse_schedule_delivery", MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes()); 通过上面的方式来发送消息,就可以让发送出去的消息是持久化的。 一旦标记了消息是持久化之后,就会让RabbitMQ把消息持久化写入到磁盘上去,此时如果RabbitMQ还没投递数据到仓储服务,结果就突然宕机了。那么再次重启的时候,就会把磁盘上持久化的消息给加载出来。 整个过程,如下图所示: 但是这里要注意一点,RabbitMQ的消息持久化,是不承诺100%的消息不丢失的。 因为有可能RabbitMQ接收到了消息,但是还没来得及持久化到磁盘,他自己就宕机了,这个时候消息还是会丢失的。 如果要完全100%保证写入RabbitMQ的数据必须落地磁盘,不会丢失,需要依靠其他的机制。 下次有机会再继续给不太熟悉MQ技术的同学,来讲解这里的东西 转载自: 石杉的架构笔记 

【MQ】扎心!线上服务宕机时,如何保证数据100%不丢失?

目录 一、写在前面 二、业务场景回顾 三、意外宕机,问题凸现 四、总结 tips 一、写在前面 上篇文章《同学,消息中间件在你们生产项目里如何落地使用的?》,我们用一个简单易懂的电商场景给大家引入说明了一个消息中间件的使用场景。 同时,我们还基于RabbitMQ的HelloWorld级别的代码,给出了订单服务和仓储服务如何基于MQ中间件收发消息的示例。 二、业务场景回顾 这篇文章,我们来稍微深入探讨一些MQ中间件使用中的基础技术问题。 首先回顾一下上篇文章做出来的一个架构图,看看订单服务和消息服务是如何基于MQ来收发消息的。 我们稍微把这个图细化一点,简单来说就是多个订单服务实例给queue推送消息,多个仓储服务每个消费一部分消息。如下图所示: 三、意外宕机,问题凸现 假如你线上对MQ技术的使用就到此为止了,那么基本可以跟offer说拜拜了。。。 因为如果是我的话,作为一个面试官就没法继续往下问了。你这个MQ的使用以及理解的深度仅此而已的话,那基本就是刚刚对MQ技术入门的程度。 如果面试官要继续问,完全可以问下面的问题: 那你说说如果仓储服务作为消费者服务,刚收到了一个订单消息,但是在完成消息的处理之前,也就是还没对订单完成仓储调度发货,结果这个仓储服务突然就宕机了,这个时候会发生什么事情? 所以说,大家还是要对这个技术了解的稍微深入一点点,否则随便被问几个问题就完蛋了。 大伙儿先来看看下面的图,感受一下车祸现场。 RabbitMQ这个中间件默认的一个行为,就是只要仓储服务收到一个订单消息,RabbitMQ就会立马把这条订单消息给标记为删除,这个行为叫做自动ack,也就是投递完成一条消息就自动确认这个消息处理完毕了。 但是接着如果此时仓储服务收到了一个订单消息,但是还没来得及对仓库系统完成商品的调度发货,结果直接就宕机了。 此时,明显这个订单消息就丢失了啊,因为RabbitMQ那里已经没有了。。。 这会导致什么样的尴尬体验呢?就是一个用户支付了8999元,对一个iphone8下了订单,结果呢,死等活等了好几天,就是不见网站上显示他的iphone8在发货。 搞了半天,原因就是他的那个iphone8的订单在仓储服务那里,还没来得及调度发货直接就宕机了,导致这个订单消息就一直丢失了,始终没有给这个用户通知仓库系统进行发货。 这个问题,是不是很尴尬?所以说,技术问题是会严重影响企业的核心业务流程的! 各位小伙伴,还记得上一讲咱们的仓储服务消费消息的代码中,有一行关键的代码: 这行代码对channel.basicConsume()方法,传入的第二个参数:true,其实就是一个关键的参数。 这个true就代表了一个核心的含义,他的意思是,RabbitMQ只要把一个消息投递到仓储服务手上,立马就标记这个消息删除了。 但是在这个默认的配置之下,要是仓储服务收到一个订单消息,结果还没来得及完成耗时几十秒的仓储调度发货的业务逻辑,结果突然宕机了,那么这个订单消息就永久性丢失了! 找了半天,原来问题的症结在这里啊!大家是不是明白了,上一篇文章最后为什么我会说,这个代码目前为止还有很多的问题。 所以这个时候,我们如果希望不要因为仓储服务的突然宕机导致一条订单消息丢失,就需要改造一下仓储服务消费消息的代码了。 首先,我们需要把那个参数从true改为false,如下代码所示: 只要修改为false之后,RabbitMQ就不会盲目的投递消息到仓储服务,立马就删除消息了,说白了就是关闭autoAck的行为,不要自作主张的认为消息处理成功了。 接着,我们需要改造一下处理订单消息的代码,如下代码所示。 这段代码,说白了,就是在对订单完成了调度发货之后,在finally代码块中手动执行了ack操作,说我自己已经完成了耗时几十秒的业务逻辑的处理,现在可以手动ack通知RabbitMQ,这个消息处理完毕了。 此时整个架构运行流程大致看起来跟下面的图那样子。 架构流程改成上面那样后,就意味着只有完成了仓储调度发货的代码业务逻辑,确保仓库系统收到通知之后,仓储服务才会在代码中手动发送ack消息给RabbitMQ。 此时,RabbitMQ收到了这个ack消息,才会标记对应的订单消息被删除了。 如果说在仓储服务收到了订单消息,但是还没来得及完成仓储调度发货的业务逻辑,那也就绝对不会执行这条订单消息的ack操作,然后RabbitMQ也就不会收到这条订单消息的ack通知。 一旦RabbitMQ发现代表消费者的某个仓储服务实例突然宕机了,而这个仓储服务收到的一些订单消息还没来得及处理,没给自己发送那些消息的ack通知。 此时,RabbitMQ会自动对这条订单消息重发推送给其他在运行中的仓储服务实例,让其他的仓储服务实例去处理这条订单消息。 这样的话,就可以保证这条订单消息不会因为某个仓储服务实例的宕机而丢失,他会确保必须由某个仓储服务实例完成这条订单消息的调度发货处理,然后才会删除那条订单消息。 四、总结 tips 最后再来一张图,大家直观的感受一下: 好了,各位同学,这篇文章是不是相对稍微深入一点点,让大家了解到了一些使用MQ技术时候要考虑的一些问题? 实际上无论是RocketMQ、Kafka还是RabbitMQ,都有类似的autoAck或者是手动ack的机制。 线上生产环境中运行时,你必须要考虑到消费者服务可能宕机的问题。 如果消费者服务没处理完消息就自己宕机了,那么一定会导致部分消息的丢失,进而影响核心业务流程的运转。 因此大家在线上使用MQ时,一定要充分考虑这些潜在问题,同时结合具体的MQ提供的一些API、参数来进行合理设置,确保消息不要随意丢失。 转载自:石杉的架构笔记 

ArrayList,Vector,LinkedList三者的比较

一、区别 1.Vector,ArrayList都是以动态数组的形式存储在内存中,LinkedList是以链表的形式进行存储的。 2.Vector,ArrayList实现了RandomAccess接口;而LinkedList实现了Deque接口,该接口又继承于Queue接口,说明LinkedList能像队列一样先进先出。 而且继承的类也有所不同,AbstractSequentialList时AbstractList的子类,实现了add,get,remove等方法。说明LinkedList的这些方法的实现和其余两个不一样,因为底层使用的是链表而不是数组。 3.Vector是线程同步的(方法加上了synchronized),其余两者不是线程同步的。 4.LinkedList适合插入和删除操作,不适合查找。ArrayList,Vector适合查找而不适合插入和删除。 5.ArrayList在扩容时扩大容器的一半,而Vector扩大容器的一倍,ArrayList更省空间。(二者默认初始容量都为10) capacityIncrement默认是0,可以在创建Vector时通过构造函数参数指定大小。 二、存储性能和特性 ArrayList,Vector都是以数组的形式来储存数据,该数组的容量大于实际存储的数据量,以便插入和增加数据,并且都可以通过下标索引数据。但是插入和删除的时候涉及到数组元素的移动,速度上会慢于LinkedList,但是查找快于LinkedList。反观LinkedList使用双向链表来储存数据,在按序号索引数据时根据在链表的前半段还是后半段向后或者向前遍历,但是插入,删除数据时只需要记录前驱节点和后驱节点即可,所以插入,删除的效率高于ArrayList和Vector。此外由于Vector使用了synchronized关键字,虽然保证了线程同步,但是无疑会影响性能。

OSPF多区域配置与心得理解

ospf 多区域 文章目录 ospf 多区域实验背景实验需求1.配置ip地址2.配置OSPF3查看R1,R4的邻居表4.强制发布一跳默认路由查看R1有没有收到默认路由 5.在R3上使用静默接口测试PC ping外网6.6.6.6 6.查看路由 实验背景 实验需求 1.配置IP地址 2.完整配置ospf多区域 3.查看邻居关系 4.强制发布默认路由 5.在R3的G0/0/1口配置静默接口 6.验证路由表 1.配置ip地址 R1 [R1]INT LOOPBACK 0 [R1-LoopBack0]IP ADDRESS 1.1.1.1 32 [R1]INT G 0/0/0 [R1-GigabitEthernet0/0/0]IP ADDRESS 20.0.0.1 30 [R1]INT G0/0/1 [R1-GigabitEthernet0/0/1]IP ADDRESS 10.0.0.1 30 R2 [R2]INT LOOPBACK 0 [R2-LoopBack0]IP ADDRESS 2.2.2.2 32 [R2]INT G0/0/1 [R2-GigabitEthernet0/0/1]IP ADDRESS 30.0.0.1 30 [R2]INT G0/0/0 [R2-GigabitEthernet0/0/0]IP ADDRESS 20.0.0.2 30 [R2]int loopback 1 [R2-LoopBack1]ip address 6.6.6.6 32 R3 [R3]INT LOOPBACK 0 [R3]IP ADDRESS 3.