长腔耗散孤子锁模光纤激光器

前言 从1989年开始,对锁模光纤激光器的研究掀起了新的热潮,这类激光器能产生超短脉冲,由于超短脉冲具有窄脉宽、高峰值功率、宽光谱等特点,在超快泵浦探测、时间分辨光谱学、超快化学及激光惯性约束核聚变等科研领域以及光信息存储[1]、材料加工[2]、激光医疗[3]、生物解剖[4]、生物医学成像[5]等工程应用领域都具有着重要的应用价值。时至今日,至少有两项诺贝尔奖的获得是与超短脉冲激光技术的应用密切相关的。美国化学家A. H. Zewail[6]由于在发展飞秒光谱技术并研究化学反应过程中寿命极短的过度态方面的成就,被授予1999年度诺贝尔化学奖。美国科学家 J. L. Hall 和德国科学家 T. W. Hänsch[7]因在基于超短脉冲的精密光谱学,特别是光学频率梳技术的开拓性工作获得了2005年诺贝尔物理学奖。因此,超短脉冲激光技术的发展对基础科学的进步具有重要意义。 和固体激光器相比,锁模光纤激光器在某些方面有着无与伦比的优势,但是它同样具有一些局限性,其中最主要的是锁模光纤激光器输出的脉冲能量较低,这限制了锁模光纤激光器的发展和应用。因此,进一步提高锁模光纤激光器的性能,尤其是提高其输出功率以及脉冲能量,具有重要的科学意义和应用价值。 1. 光纤激光器 光纤激光器,顾名思义,是由光纤作为增益介质的激光器,只是光纤不是普通的光纤,而是掺杂稀土元素的玻璃光纤。同样泵浦源、增益介质、谐振腔三个基本部分组成。由于光纤的特性,泵浦光在光纤内极易形成高功率密度,造成激光工作物质的激光能级粒子束反转,当加入正反馈回路(谐振腔),即可形成激光震荡,从而输出激光,输出波长由光纤中所掺的杂质决定。 图1 光纤激光器 2. 锁模光纤激光器: 再简单介绍一下锁模光纤激光器。 所谓锁模,就是对激光器中运转在位于增益带宽内诸多纵模进行相位锁定,它是对激光进行的一种特殊的调制,最终结果就是使得不同的振荡纵模之间建立起了确定的相位关系,从而使各个模式产生相干叠加,从而在时域上形成一种超短激光脉冲[8]。 由于光纤激光器的谐振腔结构比较灵活,可以是环形腔,也可以是线形腔,而且谐振腔内可以调节的参数很多,所以,可以很灵活的利用锁模技术产生超短脉冲。另外,光纤激光器具有全光纤结构,当在谐振腔内传输的光脉冲能量较高时,光纤将表现出比较强的非线性效应,比如自相位调制效应(SPM)、交叉相位调制效应(XPM)等,利用这些效应不仅能够实现锁模,而且还可以改善激光器输出的锁模脉冲的质量。 锁模技术的实现方式通常有两种:主动锁模和被动锁模。两种技术的区别是:主动锁模需要在谐振腔内插入一个有源的主动调制器来实现锁模,而被动锁模是通过可饱和吸收体等无源光器件来实现的。 2.1 主动锁模光纤激光器 主动锁模光纤激光器采用周期性调制谐振腔内参量的方法,即在谐振腔内插入一个受外部信号控制的调制器,通过控制调制器的调制频率和调制深度来周期性的改变谐振腔内各个振荡纵模间的相位和振幅。当选择的调制频率和谐振腔内各个纵模间的间距相等时,谐振腔内可以形成锁模脉冲序列。 图2 主动锁模光纤激光器原理图(掺铒光纤为例) 2.2被动锁模光纤激光器 被动锁模光纤激光器利用一些光学元件对脉冲强度的非线性响应,实现脉冲窄化。可以使用的方法有:利用半导体可饱和吸收镜(SESAM),单壁碳纳米管(SWCNT),和石墨烯,或者利用非线性效应,包括非线性偏振旋转(NPR),非线性放大环形镜(NALM),以及非线性光环形镜(NOLM)结构。 图3 基于NPR的被动锁模光纤激光器原理图(掺铒光纤为例) 3. 耗散孤子锁模光纤激光器 进一步,我们来说说耗散孤子的锁模光纤激光器。提高激光输出脉冲一直是研究的热点,传统孤子锁模光纤激光器受到孤子面积理论的影响,当谐振腔内泵浦功率过高,会导致孤子脉冲分裂,所以其脉冲宽度和能量都受到了限制。展宽脉冲锁模光纤激光器,将光纤激光器分为正色散部分和负色散部分。脉冲在谐振腔内传输时会被周期性的展宽和压缩,从而降低了脉冲的平均峰值功率,减少了脉冲在传输过程中积累的非线性相移,避免了脉冲的分裂。虽然脉冲功率升高,但是也只能限制在几个nJ。 耗散孤子光纤激光器是耗散结构的一种,耗散结构是指一个远离平衡态的开放系统,通过与外界交换物质和能量,在一定条件下形成的一种新的稳定有序的结构。 耗散孤子光纤激光器的脉冲形成机制完全不同于传统孤子光纤激光器,如图4所示。传统孤子是色散和光纤非线性效应对脉冲平衡作用的结果,它的形成过程中没有能量的流入和流出。而在正色散区,色散效应和非线性效应共同作用于脉冲使脉冲展宽,在光纤激光器中通过直接利用增益介质本身的增益带宽限制,可以补偿色散效应和非线性效应的综合作用结果,从而得到耗散孤子。在耗散孤子的形成过程中,激光器的增益和损耗也起到非常重要的作用。 图4(a)传统孤子与(b)耗散孤子形成机理对比示意图 耗散孤子具体形成机理如下:对于正色散腔掺铒锁模光纤激光器而言,在频域上,脉冲在EDF的放大过程受到自相位调制等非线性效应的影响,导致脉冲的时域前沿产生红移,时域后沿产生蓝移;时域上,由于谐振腔内的净色散为正,导致长波成分传播速度大于短波成分。因此,光纤非线性和正色散效应的共同作用导致时域脉冲宽度急剧增大,并产生极大的正频率啁啾。此外,由于谐振腔内的EDF长度较大,导致其对腔内传输的脉冲具有强烈的增益色散作用[9],增益滤波效应明显。这意味着,当脉冲在EDF中传输时将受到有效增益滤波作用,同时滤除脉冲的频域和时域的前后沿。当脉冲经过可饱和吸收体时(自然可饱和吸收体或等效可饱和吸收体),时域脉冲宽度被进一步窄化,并且频域光谱两翼部分也同时被削弱(此为耗散过程),在增益、损耗、正色散、光纤非线性效应、光谱滤波效应和可饱和吸收效应的共同作用下,光脉冲在谐振腔内实现了稳定的自洽演化,从而获得了稳定的耗散孤子脉冲。 耗散孤子的形成过程中,在谐振腔内正色散的影响下,脉冲被极大的展宽,降低了脉冲的峰值功率和非线性效应,因此耗散孤子光纤激光器能有效克服光波分裂,实现更高能量的锁模脉冲输出。 例如2005年,Ruehl[10]等人搭建了极大正色散腔掺铒光纤激光器,实验获得了脉冲宽度为64fs,脉冲能量为6.4nJ的耗散孤子脉冲。 2006年,Chong等人[11]搭建了全正色散掺镱光纤激光器,并获得了能量大约为20nJ的耗散孤子脉冲,脉冲经过压缩后峰值功率可以达到100kW以上。 2010年,Lefrancois等人[12]采用大模场面积光子晶体光纤构建了正色散腔锁模光纤激光器,实现了能量为142nJ的耗散孤子输出,脉冲经腔外解啁啾压缩后脉冲宽度为115fs,峰值功率达兆瓦以上。 4. 长腔耗散孤子锁模光纤激光器 那么为什么需要用长腔的光纤激光器呢? Renninger[13]等通过数值模拟,发现耗散孤子脉冲的宽度、啁啾、和能量都随着腔内净色散量的增加而增大。而在光纤激光器中,单纯增加光纤的长度即可获得传统固体激光器中所无法得到的极大色散量;同时,光腔长度的增加意味着锁模脉冲重复频率下降;由光纤波导构成的谐振腔又能够有效降低外界环境不稳定性的影响。因此,长腔的全正色散锁模光纤激光器有望直接输出稳定的高能量、低重复频率的高啁啾宽脉冲。 2008年,Renninger等[14]利用60多米长的环形腔掺镱全正色散锁模光纤激光器产生了3.2MHz,15nJ 的锁模脉冲。 2009年,M.Zhang等[15]利用长达1.6km的线形腔掺镱光纤激光器在全正色散域获得了191kHz,75.2nJ的锁模脉冲输出。实验结构如下: 图5 线形腔掺镱光纤激光器实验装置结构图 2010年,赵慧等[16]报道了一种长腔掺镱锁模光纤激光器,采用全单模光纤结构,腔内无色散补偿元件,工作在全正色散域,仅引入窄带滤波器参与耗散孤子的形成,通过延长单模光纤长度得到了重复频率6.66MHz,功率12nJ和重复频率5.05MHz,功率20nJ的耗散孤子脉冲。利用较短腔长产生了较高的单脉冲能量。结构如下图: 图6 全正色散锁模掺镱光纤激光器实验装置结构图 自由空间光路由四分之一波片,二分之一波片和偏振分束器构成,与光纤中的弱双折射和光克尔效应共同提供NPR机制。窄带滤波器SF引入频域的幅度调制。单模光纤SMF1分别取26.6m和36.7m,实现了不同脉冲输出功率,和重复频率。 而以往典型的全正色散锁模掺镱激光器一般工作在几十甚至上百兆赫兹的重复频率下,单脉冲能量只能达到几个纳焦耳甚至更低[17]。可见长腔的全正色散锁模光纤激光器在降低重复频率、提高单脉冲能量方面具有很大的优势。 2014年,吉林大学许阳等[18]利用自制的碳纳米管薄膜(CNT)提供可饱和吸收效应,同样使用窄带滤波器SF窄化脉冲,引入耗散机制,产生耗散孤子。通过SF的一定长度的尾纤,使得腔长为15m,25m,49m。结构图如下: 图7 实验装置结构图(采用CNT) 根据不同腔长得到了重复频率13.3MHz,脉宽530ps,重复频率8MHz,脉宽610ps以及重复频率4.08MHz,脉宽720ps的脉冲。实现了耗散孤子的锁模脉冲。 2015年,哈尔滨工业大学王玉宝等[19]使用单壁碳纳米管和10m双包层掺镱光纤搭建超长腔锁模光纤激光器。实现重复频率199.8kHz,脉宽小于1ns的耗散孤子锁模脉冲输出。同样,使用非线性偏振旋转效应也实现了掺镱耗散孤子锁模光纤激光器。 2017年,北京邮电大学的刘红玉等[20]搭建了腔长为500m的长腔被动锁模激光器,获得了重复频率为390.118kHz,脉冲的能量大于100nJ的锁模脉冲输出。采用如下实验结构: 图8 实验装置结构图 同时提出存在的问题:采用长腔来获得高能量脉冲的方式面临着腔长过长会引入过多的非线性效应以及色散等影响锁模以及后续脉冲压缩的问题,目前能够压缩到的脉冲宽度是理论变换极限值(transform-limited)的数倍。同时实验验证了高阶色散不是影响脉冲不能压缩到理论变换极限值的决定性因素。 5. 结语 总结一下,通过在大正色散的长腔内引入耗散机制或者直接利用增益介质本身的增益带宽限制,便可抑制脉冲的分裂,配合主动锁模或者被动锁模结构,从而获得高能量,低重频的超短脉冲,在许多科研领域以及工程应用领域都具有着重要的应用价值和前景。相信经过相关科研人才的不懈努力与创造,该光纤激光器在该方向能够有巨大的发展,从而促进社会发展,造福人类。

Hystrix浅入浅出:(二)断路器和滑动窗口

上文《Hystrix浅入浅出:(一)背景与功能初探》已经提到过,使用Hystrix我们需要将自动熔断的业务逻辑通过Command模式来包装,于是,我们只需要继承HystrixCommand抽象类,实现run、getFallback等方法,你就拥有了一个具有基本熔断功能的类。从使用来看,所有的核心逻辑都由AbstractCommand(即HystrixCommand的父类,HystrixCommand只是对AbstractCommand进行了简单包装)抽象类串起来,从功能上来说,AbstractCommand必须将如下功能联系起来: 策略配置:Hystrix有两种降级模型,即信号量(同步)模型和线程池(异步)模型,这两种模型所有可定制的部分都体现在了HystrixCommandProperties和HystrixThreadPoolProperties两个类中。然而还是那句老话,Hystrix只提供了配置修改的入口,没有将配置界面化,如果想在页面上动态调整配置,还需要自己实现。 数据统计:Hystrix以命令模式的方式来控制业务逻辑以及熔断逻辑的调用时机,所以说数据统计对它来说不算难事,但如何高效、精准的在内存中统计数据,还需要一定的技巧。 断路器:断路器可以说是Hystrix内部最重要的状态机,是它决定着每个Command的执行过程。 监控露出:能通过某种可配置方式将统计数据展现在仪表盘上。 一. Hystrix内部流程 本文将主要阐述【断路器】和【数据统计】两大组件的设计和实现。在介绍两大组件之前,我们先简单了解下Hystrix工作时的内部流程,官方的图有些复杂(https://github.com/Netflix/Hystrix/wiki/How-it-Works),过于细节,这里画个简单的(只显示了关键环节): 上图简单罗列的一个请求(即我们包装的Command)在Hystrix内部被执行的关键过程。 【创建Command对象】这一过程也包含了策略、资源的初始化,参看AbstractCommand的构造函数: protected AbstractCommand(...) { // 初始化group,group主要是用来对不同的command key进行统一管理,比如统一监控、告警等 this.commandGroup = initGroupKey(...); // 初始化command key,用来标识降级逻辑,可以理解成command的id this.commandKey = initCommandKey(...); // 初始化自定义的降级策略 this.properties = initCommandProperties(...); // 初始化线程池key,相同的线程池key将公用线程池 this.threadPoolKey = initThreadPoolKey(...); // 初始化监控器 this.metrics = initMetrics(...); // 初始化断路器 this.circuitBreaker = initCircuitBreaker(...); // 初始化线程池 this.threadPool = initThreadPool(...); // Hystrix通过SPI实现了插件机制,允许用户对事件通知、处理和策略进行自定义 this.eventNotifier = HystrixPlugins.getInstance().getEventNotifier(); this.concurrencyStrategy = HystrixPlugins.getInstance().getConcurrencyStrategy(); HystrixMetricsPublisherFactory.createOrRetrievePublisherForCommand(this.commandKey, this.commandGroup, this.metrics, this.circuitBreaker, this.properties); this.executionHook = initExecutionHook(executionHook); this.requestCache = HystrixRequestCache.getInstance(this.commandKey, this.

华为eNSP静态路由下一跳实验

一、实验目的: 主机之间实现互相通信,要求路径: PC1和PC2-->PC3和PC4:R2--->R1---->R3 PC1和PC2-->PC5:R2--->R4 PC3和PC4-->PC1和PC2:R3--->R4---->R1--->R2 PC3和PC4-->PC5:R3--->R1---->R4 二、实验内容 配置静态路由,实现各个主机互通。 三、实验环境 eNSP模拟器 四、实验步骤 1、搭建实验环境图 2、配置各个路由器的IP地址。 R2: R3: R4: R1: 3、配置好IP地址后主机1.2能互通,1和3不通。 4、配置静态路由 5、ping各个主机查看连通性。 五、实验结果 配置IP地址之前,各个主机都不通,配置好IP后各个主机可以ping通各自的网关和连接在同一交换机上的主机,然后手动配置静态路由:ip route-static 192.168.3.1(目的地址) 24(掩码位数) 192.168.12.1(下一跳),配置好之后就可以实现各主机之间的互通。 六、总结 在配置静态路由的时候多配置了一条路由,导致主机无法互通,在配置了两条路由后就会先找数据大的一条,如果此条不通,不会再去寻找别的路由,就会丢弃数据,配置过程就要细心,路由器每个接口都是独立的广播域。

直连路由-静态路由-链路聚合

一、实验目的: 使用直连路由、静态路由和链路聚合方式实现全网互通。 二、实验内容 四台主机处于不同的vlan中,两台交换机利用链路聚合实现互通,利用静态路由配置交换机,达到全网互通的效果。 三、实验环境 eNSP模拟软件 四、实验步骤 1、如图搭建网络环境。 2、在交换机1中创建vlan 10 30 12,配置网关,并将主机1加入到vlan 10,主机2加入到vlan 30,vlan 12用于两个交换机之间的聚合。 3、同理处理第二个交换机、主机3和主机4。(vlan 40 20 12) 4、查看两个交换机中的路由信息 5、测试主机1和主机4之间的连通性 6、聚合两个交换机。 8、手动配置静态路由 五、实验结果 1、创建了四个vlan之后,各个主机之间是不互通的,将主机1和主机2分别加入到vlan 10 和vlan 30 中,并给第一个交换机配置网关后,主机1和主机2互通,主机3和主机4同理,但主机1 2 不能和主机3 4 互通。 vlan batch 10 30 12/ interface vlanif 10/ Ip address 192.168.1.1(网关) 2、 交换机聚合之后主机1可以ping通第二个交换机的网关,但不能和主机3 4互通。interface Eth-trunk 1 (创建逻辑聚合接口) / interface GigabitEthernet 0/0/1 /eth-trunk 1(将实际接口加入到聚合口) 两个交换机同等处理。 3、配置静态路由,聚合链路之后两个路由表里还是没有另外两边的主机IP,所以手动配置。IP route-static 192.168.2.100 24 192.168.12.2 目的地址 掩码数 下一跳 都配置好之后,就能实现全网互通了。

华为eNSP模拟器vlan 隔离技术的实现

一、实验目的: 使用vlan技术隔离不同的用户,减小冲突域的范围 二、实验内容 1、 在不使用vlan技术的情况下测试4台主机之间是否可以相互通信。 2、测试不同的vlan下用户主机之间是否可以相互通信。 3、使用vlan技术的优点。 三、实验环境 华为eNSP模拟软件。 四、实验步骤 1、建立实验模型图。 Pc1和pc2在vlan 10中,pc3和pc4在vlan 20中。 2、测试各个主机之间的连通性。 用pc1抓包,pc2发送ping命令查找pc3的IP地址,pc1上也收到了广播的信息,但没回复。3、用vlan技术隔离广播网域。 (1)创建vlan10和vlan20。 (2)将Ethernet 0/0/1 和Ethernet 0/0/2 加入到vlan 10 中,将Ethernet 0/0/3和Ethernet 0/0/4加入到vlan20中。 (3)再次测试四台主机的连通性。 五、实验结果 1、未配置vlan时,四台主机是互通的。 2、配置vlan 10 20 ,然后将Ethernet 0/0/1 和Ethernet 0/0/2 加入到vlan 10 中,将Ethernet 0/0/3和Ethernet 0/0/4加入到vlan20中。Pc1和pc2是互通的,不能连接到pc3和pc4中,pc3和pc4是连通的。 

react框架设计原理及生命周期

1、ReactJS的背景 1、react是Facebook为实现其内部广告系统项目设计的一种前端界面构建方式 2、前端工程师的职责就是把逻辑数据实时反应到view层,既然涉及到vie层, 那就涉及到dom树。而大家都知道,复杂或者频繁的操作dom通常是造成性能 不好的地方。 3、所以设计react的地方就是其虚拟dom 2、ReactJS的设计原理 react的设计原理就是其引入的虚拟dom机制: 1、react用javascript在浏览器端实现了一套虚拟dom api。 2、基于react开发的时候所有的dom构造都是基于虚拟dom进行的 3、每当有state更改的时候,react就重新render一整套虚拟dom树, react机制会将当前的整个dom树和上一次的dom树进行对比 取到diff,进行真实的dom更改。 4、其实state也有一部分实现的是数据、html片段绑定, 直接更新的数据是包含的 其实说到这里,往深一点考虑就是react的虚拟dom的diff算法 从大层面上来讲 深层次一点就是react的diff算法是怎么理解的。 错误的见解:我曾经以为diff算法,就是深层次的diff,算法运算时只比较 不同的。但其实当时浅显的想法,确实是diff运算的结果,但不是 diff运算的算法。 1、tree diff 也叫层级diff, 针对上图 React对Virtual DOM树进行层级控制,只会对相同层级的DOM节点进行比 较,即同一个父元素下的所有子节点,当发现节点已经不存在了,则会删除掉 该节点下所有的子节点,不会再进行比较。这样只需要对DOM树进行一次遍 历,就可以完成整个树的比较。 即使说a节点以及他的子节点被移动,但是react只关注同级比较,在第二层 把a及其子节点删了,在第三层再重新创建,所以diff运算量大,影响性能 不建议setState直接更改树的结构。最好是state颗粒度小,只改变树中 的某一个小的节点,那么diff的时候只会深度比较这一个小节点。 2、componnet diff 假如说因为某个条件切换,所以要显示不同的组件。 1、比较两个组件的类型(D和G) 2、如果(D和G)不是同一类型,进行diff算法,分析会影响性能 直接删掉上一个虚拟dom组件。 重新创建新的组件。 如果是同一类型的组件,会按照层级策略深层对比每个节点。 3、element diff 精确的对属于同一层级的节点diff时,提供了3种节点操作,分别为INSERT_MARKUP(插入),MOVE_EXISTING(移动),REMOVE_NODE(删除)。 如果同一层级,没有这个新节点会新增插入 如果同一层级,如果有新节点,但是属性不一样,会复用节点,赋值属性 如果同一层次,旧dom有,新dom没有,会删除这个节点。 总结:setState()触发一次组件重绘,其实就是虚拟dom重新生成,除非在 shouldComponentUpdate()中实现了一些条件渲染逻辑。来允许和阻止是否需要 调用指定组件的 render 方法。其实这个深入逻辑就是他触发了render,只是是 否触发了内部的diff算法,return false 的时候,不diff,render出来的新 旧dom一样。diff算法的复杂度为0。 React的核心 1、使用组件定义界面,是一个View层的前端库,界面可能由 一个或者多个组件构建而成 react的虚拟DOM是如何反映到真实的DOM树上的? 解答:首次渲染大量DOM时,由于多了一层虚拟DOM的计算,会比 innerHTML插入慢。虚拟DOM可以确保只对界面上真正变化的部分进行 实际的DOM操作。 比如: 替换节点就需要调原生JS对象的repaceChild()接口; 对于修改属性,则要调setAttribute()接口等等。 3、react 生命周期

内核NFS-V4部署服务,挂载,ACL使用

2019独角兽企业重金招聘Python工程师标准>>> v4挂载服务端设置 vim /etc/exports /tmp *(fsid=0,rw,sync,no_root_squash,acl) /tmp/nfsdata *(rw,sync,no_root_squash,acl) 客户端挂载 mount.nfs4 ip:/nfsdata /mnt/nfs 导出IP设置 [root@rootbug ~]#vim /etc/exports /share/iso *(ro) --把/share/iso 共享给*(代表所有IP) ro (代表只读) /share/iso *(rw) --rw代表可读可写 /share/iso 10.10.10.0/24(ro) --只共享给10.10.10的网段的计算机访问 /share/iso 10.10.10.0/255.255.255.0(ro) /share/iso 10.10.10.10/255.255.255.255(ro) --定义只10.10.10.10这台计算机可以访问 /share/iso 10.10.10.10(ro) /share/iso 10.10.10.10/32(ro)10.10.10.254/32(rw) --定义只有10和254这两台可以访问 NFSv4和NFSv3的差别如下: (1) NFSv4设计成了一种有状态的协议,自身实现了文件锁功能和获取文件系统根节点功能,不需要NLM和MOUNT协议协助了。 (2) NFSv4增加了安全性,支持RPCSEC-GSS身份认证。 (3) NFSv4只提供了两个请求NULL和COMPOUND,所有的操作都整合进了COMPOUND中,客户端可以根据实际请求将多个操作封装到一个COMPOUND请求中,增加了灵活性。 (4) NFSv4文件系统的命令空间发生了变化,服务器端必须设置一个根文件系统(fsid=0),其他文件系统挂载在根文件系统上导出。 (5) NFSv4支持delegation。由于多个客户端可以挂载同一个文件系统,为了保持文件同步,NFSv3中客户端需要经常向服务器发起请求,请求文件属性信息,判断其他客户端是否修改了文件。如果文件系统是只读的,或者客户端对文件的修改不频繁,频繁向服务器请求文件属性信息会降低系统性能。NFSv4可以依靠delegation实现文件同步。当客户端A打开一个文件时,服务器会分配给客户端A一个delegation。只要客户端A具有delegation,就可以认为与服务器保持了一致。如果另外一个客户端B访问同一个文件,则服务器会暂缓客户端B的访问请求,向客户端A发送RECALL请求。当客户端A接收到RECALL请求时将本地缓存刷新到服务器中,然后将delegation返回服务器,这时服务器开始处理客户端B的请求。 (6) NFSv4修改了文件属性的表示方法。由于NFS是Sun开发的一套文件系统,设计之出NFS文件属性参考了UNIX中的文件属性,可能Windows中不具备某些属性,因此NFS对操作系统的兼容性不太好。NFSv4将文件属性划分成了三类: Mandatory Attributes: 这是文件的基本属性,所有的操作系统必须支持这些属性。 Recommended Attributes: 这是NFS建议的属性,如果可能操作系统尽量实现这些属性。 Named Attributes: 这是操作系统可以自己实现的一些文件属性。 (7)服务器端拷贝: 如果客户需要从一个NFS服务器拷贝数据到另外一个NFS服务器,nfsv4可以让两台NFS服务器之间直接拷贝数据,不需要经过客户端。 (8)资源预留和回收: NFSv4为虚拟分配提供的新特性。随着存储虚拟分配功能的普及使用,nfsv4可以为预留固定大小的存储空间;同样在文件系统上删除文件后,也能够在存储上面释放相应空间。 (9)国际化支持: NFSv4文件名、目录、链接、用户与组可以使用 UTF-8字符集,UTF-8兼容ASCII码,使得NFSv4支持更多语言。 (10)RPC合并调用: NFSv4允许将多个请求合并为一个rpc引用,在NFSv3每个请求对应一个rpc调用。WAN环境中,NFSv4合并rpc调用可以显著降低延迟。

Word 交叉引用如何调整引用顺序?

只需要在论文后面的参考文献部分修改即可,正文中的引用相当于超链接,”Ctrl+鼠标左键” 即可进入引用的具体内容(参考文献),我们在调整引用顺序的时候,在需要调整的某条参考文献处,从后往前拖动鼠标选中整个参考文献内容,选完后面会把空格也选上了,没关系,一起剪切过去,然后插入到你想放的位置。一般第一条参考文献的位置先预留下来,主要是第一条不好调整位置,方便后面的参考文献往前调整(可以在第一条参考文献的末尾按下 Enter 键,既多了一个参考文献内容为空的“[2] ”,然后将第一条参考文献从后往前剪切到参考文献的末尾(方便找),这时,之前参考文献内容为空的“[2] ”的索引下标升级为“[1] ”)。 回想起来,从后往前(连带后面的空格符)的复制粘贴会将原文的格式一起粘贴过去,放到文献引用就是将引用()和具体内容一起移动了,这跟复制标题格式的思路是一样的。

TensorFlow学习系列之八:什么是数据流图?

一、概述 TensorFlow最基本的一次计算流程通常是这样的:首先它接受n个固定格式的数据输入,通过特定的函数,将其转化为n个张量(Tensor)格式的输出。 一般来说,某次计算的输出很可能是下一次计算的(全部或部分)输入。整个计算过程其实是一个个Tensor 数据的流动过程。在这其中,TensorFlow将这一系列的计算流程抽象为了一张数据流图(Data Flow Graph)。简单来说,数据流图,就是在逻辑上描述一次机器学习计算的过程。下面我们以图11-26为例,来说明TensorFlow的几个重要概念。 图11-26 TensorFlow的数据流图 构建数据流图时,需要两个基础元素:点(node)和边(edge)。 • 节点:在数据流图中,节点通常以圆、椭圆或方框表示,代表对数据的运算或某种操作。例如,在图11-26中,就有5个节点,分别表示输入(input)、乘法(mul)和加法(add)。 • 边:数据流图是一种有向图,“边”通常用带箭头线段表示,实际上,它是节点之间的连接。指向节点的边表示输入,从节点引出的边表示输出。输入可以是来自其他数据流图,也可以表示文件读取、用户输入。输出就是某个节点的“操作(Operation,下文简称Op)”结果。在图11-26中的例子中,节点c接受两个边的输入(2和4),输出乘法的(mul)结果8。 在本质上,TensorFlow的数据流图就是一系列链接在一起的函数构成,每个函数都会输出若干个值(0个或多个),以供其它函数使用。在图11-26中,a和b是两个输入节点(input)。这类节点并非可有可无,它的作用是传递输入值,并隐藏重复使用的细节,从而可对输入操作进行抽象描述。 除了上述两个概念之外,下面3个概念也很重要,在后面的章节会详细介绍,这里仅做简单介绍。 (1)Session(会话):根据上下文(context),会话负责管理协调整个数据流图的计算过程。光有数据流图还不够,如果想执行数据流图所描述的计算,还得配备一个专门的会话,来负责图计算。 (2)Op(操作):就是数据流图中的一个节点,代表一次基本的操作过程。 (3)Tensor(张量):在TensorFlow 中,所有计算数据的格式,都是一个n维数组,如 t = [[1, 2, 3], [4, 5, 6], [7, 8, 9]],就是一个2维张量。 二、构建第一个TensorFlow数据流通过前面的介绍,下面我们就可以构建一个与图11-26相匹配的数据流程图,具体代码如下所示: 【范例11-1】TensorFlow数据流图(feed_dict.py) import tensorflow as tf a = tf.constant(4, name = "input_a") b = tf.constant(2, name = "input_b") c = tf.multiply(a,b, name ="mul_c") d = tf.add(a,b, name = "add_d") e = tf.add(c,d, name = "add_e") sess = tf.Session() print(sess.run(e)) sess.

通过Jquery和Ajax初始化加载页面数据

最近前端崩了。。不得不亲自爬过来学习写Jquery了。。 进入页面时,不需要任何点击,就主动通过Ajax发送post请求,并接收返回数据,在success中进行页面数据的填充 返回的json格式为{ code: 0, msg: "成功", data: - { name: "jjjj", email: "1342746626@qq.com", password: "7777777", phone: "222333", address: "sdsd", birthday: "2018-01-02", icon: "/usericon/1525692516504IWZ/2018-05-10/739c9a89-c539-49dd-baa9-d08999644c7b.png" } } <script type="text/javascript"> //加载初始化数据 function initData(){ $.ajax({ type:'GET', dataType: "json", url:"../user/center", /*data:{ email:$("#email").val(), password:$("#password").val() },*/ success:function(res){ alert("加载数据"); if(res.code=="0"){ console.log(res); alert(res.msg); var info = res.data; $("#name").attr("value", info.name); $("#email").attr("value", info.email); $("#password").attr("value", info.password); $("#phone").attr("value", info.phone); $("#address").attr("value", info.address); $("#birthday").attr("value", info.birthday); $("#picture").attr("src", info.icon); }else{ alert("用户信息不合法,或邮箱已被占用"); } }, error:function(){ // $("

字符串,二进制相互转换

package cn.ibaner.corp.constants; public class StrToBinary { public static String StrtoBinary(String str){ char[] strChar=str.toCharArray(); String result=""; for(int i=0;i<strChar.length;i++){ result +=Integer.toBinaryString(strChar[i])+ " "; } return result; } public static String BinaryToStr(String binary){ String[] tempStr=binary.split(" "); char[] tempChar=new char[tempStr.length]; for(int i=0;i<tempStr.length;i++) { tempChar[i]=BinstrToChar(tempStr[i]); } return String.valueOf(tempChar); } private static int[] BinstrToIntArray(String binStr) { char[] temp=binStr.toCharArray(); int[] result=new int[temp.length]; for(int i=0;i<temp.length;i++) { result[i]=temp[i]-48; } return result; } private static char BinstrToChar(String binStr){ int[] temp=BinstrToIntArray(binStr); int sum=0; for(int i=0; i<temp.

阿里云服端口无法访问,已解决

第一步,先到阿里云服添加安全组,某些云平台做了云安全端口限制,就是本机打开了,云平台没开也是无法访问的 云平台端口问题解决: centos7防火墙管理 查看已经开放的端口: firewall-cmd --list-ports 开启端口 firewall-cmd --zone=public --add-port=80/tcp --permanent

训练分类器为什么要用cross entropy loss(交叉熵损失函数)而不能用mean square error loss(MSE,最小平方差损失函数)?

在一个人工智能群里,有人问起,训练分类器为什么要用cross entropy loss(交叉熵损失函数)而不能用mean square error loss(MSE,最小平方差损失函数)呢? 正好,在我的那本《深度学习之美》(第11章)提及这个问题,于是复制了一部分内容,作为回答,群里的同学觉得通俗易懂,于是,把我的回答贴到这里,算是一个总结: --------- 对于多分类的标签(即教师信号),从本质上看,通过One-hot操作,就是把具体的标签(Label)空间,变换到一个概率测度空间(设为 p),如[1,0,0](表示它是第一个品类)。可以这样理解这个概率,如果标签分类的标量输出为1(即概率为100%),其它值为0(即概率为0%)。 而对于多分类问题,在Softmax函数的“加工”下,神经网络的实际输出值就是一个概率向量,如[0.96, 0.04, 0],设其概率分布为q。现在我们想衡量p和q之间的差异(即损失),一种简单粗暴的方式,自然是可以比较p和q的差值,如MSE(不过效果不好而已)[1]。 一种更好的方式是衡量这二者的概率分布的差异,就是交叉熵,因为它的设计初衷,就是要衡量两个概率分布之间的差异。 图1 Softmax输出层示意图 为什么要用softmax一下呢?exp函数是单调递增的,它能很好地模拟max的行为,而且它能让“大者更大”。其背后的潜台词则是让“小者更小”,这个有点类似“马太效应”,强者愈强、弱者愈弱。这个特性,对于分类来说尤为重要,它能让学习效率更高。 举例来说,在图1中,原始的分类分数(或者说特征值)是[4, 1, -2],其中“4”和“1”的差值看起来没有那么大,但经过Softmax“渲染”之后,前者的分类概率接近于96%,而后者则仅在4%左右。而分值为“-2”的概率就“更惨”了,直接趋近于0。这正是Softmax回归的魅力所在。 这样一来,分类标签可以看做是概率分布(由one-hot变换而来),神经网络输出(经过softmax加工)也是一个概率分布,现在想衡量二者的差异(即损失),自然用交叉熵最好了。 参考文献: [1] Golik P, Doetsch P, Ney H. Cross-Entropy vs. Squared Error Training: a Theoretical and Experimental Comparison[C]// Interspeech. 2013:1756-1760. 节选自 张玉宏 《深度学习之美》第11章,电子工业出版社,博文视点,2018年6月出版

Tensorflow入门1-CNN网络及MNIST例子讲解

1. 前言 人工智能自从阿尔法狗大败李世石后就异常火爆,最近工作中需要探索AI在移动端的应用,趁着这个计划入门下深度学习吧。 深度学习的入门曲线还是很陡峭的,看了很多资料,询问了从事相关工作的朋友后终于有点感觉了,这篇文章就讲一下我在这个过程中的所见所得吧,肯定是不专业的,如果所说有什么错误,也希望大家帮忙指出,共同进步。 这个入门的文章准备分以下几个部分来说: CNN的原理Tensorflow使用CNN网络解决MNIST问题的例子讲解Demo改造解决我自己的股票图片识别问题训练出的模型部署到iOS端的Tensorflow Mobile框架中训练出的模型部署到iOS端的Tensorflow List框架中 首先我做的第一件事是分清楚一些概念,之前完全不懂得时候只觉得人工智能很厉害,能解决人力解决不了的问题,但人工智能到底是什么,完全不知道。既然要学习,首先就得分清楚人工智能,机器学习,深度学习都是些什么东西,需要从哪里入手等等这些问题。这个问了从事相关工作的同学后再查阅了一些资料后,很容易的就理解了。知乎上的这个回答比较靠谱,传送门,总结一下就是这两句话。 机器学习:一种实现人工智能的方法 深度学习:一种实现机器学习的技术 而三者的关系就是 可以看的出来,人工智能是一个很大的概念,想用机器来解决问题的一种思想都可以认为是人工智能,而这个概念早在19世纪50年代就提出了。机器学习就是实现人工智能的一种方法,一切使用数据分析帮助决策的场景都可以叫做机器学习,这个概念从19世纪80年代到现在也已经发展了快40年了,机器学习其实一点都不神秘,在现代生产中的应用随处可见,比如各种网站的推荐算法,垃圾邮件的过滤算法等等。而最近火热的概念其实人工智能中很小的一部分,叫做深度学习。简单来说,使用深度神经网络去解决问题的学习方法叫做深度学习。如果说广义的机器学习是人类定义好规则,让计算机去做,那么深度学习就是人类定义好规则后,让计算机去学。深度学习依赖于现在计算能力的提升飞速发展,在图像识别、语音识别等领域发挥了巨大的作用。看完这篇文章后,你应该对深度学习会有一个简单的理解。 考虑到机器学习的算法实在是太多,学习需要很多时间(按照我粗浅的理解,机器学习就是一整部统计学在计算机界的应用,很大)。而深度学习就相对单纯一些,据我所知,目前比较流行的深度学习算法就只有CNN(卷积神经网络),RNN(循环神经网络)和DNN(深度神经网络)。DNN是整个深度学习的基础,后面的CNN和RNN其实都是基于DNN来做的,CNN(卷积神经网络)比较擅长于提取图片特征,处理图像问题。RNN是把前一次网络的输出作为下一次网络的输入,让整个网络有了前因后果的概念,比较擅长处理有前后时间序列关系的问题,比如语音识别,语义分析等。 根据之前列的大纲,这篇文章会先讲一下CNN网络的概念,然后讲一下Tensorflow中一个很有用的例子,用CNN网络去解决MNIST问题。大纲中剩下的部分会在接下来的文章中讲解。 2. CNN神经网络 CNN神经网络,全称是卷积神经网络,是目前深度学习中最常见、应用最广泛的一种网络,适合于解决图像识别,图片分类,图像预测的问题。 这里有一篇讲CNN比较好的文章,我看到很多大V讲到CNN的时候也会引用这篇文章的内容。有兴趣可以先看一下这篇文章。 An Intuitive Explanation of Convolutional Neural Networks 译文:什么是卷积神经网络?为什么它们很重要? 如果不考虑CNN,可以先思考下一个自己去实现一个分类图片的程序会怎么做。我之前做了一个判断一张图片是否是自选股截图的程序,自选股截图指的是下面这种图片。 首先我会去看这种图片有什么特征,很明显,自选股截图上面有规则的红绿方块,而其他图片是没有的。那么在程序中,我首先提取出图片的各个像素值,如果去查找这张图片中是否有这种红绿色块,查找红绿色块的算法,可以这样做,看红色的像素值的坐标是否是一个方块,或者绿色的像素值的坐标是否是一个方块。 由上所知,一个典型的图片分类算法就是提取特征,比较特征。CNN网络简单来说就是将这个过程自动化,开发人员不需要告诉网络图片的特征是什么,CNN网络可以自动的从图片中寻找特征,并记录。这个过程是怎么做到的呢,下面来讲。 输入一张图片,网络通过一系列的运算,提取出图片的特征。如下图所示: 当然,这中间的一系列计算是有算法和参数的。训练的时候我们会给每张图片打上一个对应的标签,CNN通过上面一系列计算出特征后,每个特征就对应着一个标签。比如 特征1 -> 标签A 特征2 -> 标签B 特征3 -> 标签A 当下一张图进入训练时,CNN网络仍然以上次训练计算出来的参数去提取特征,假如提取出的是特征2,如果图片的标签是B,那么证明参数正确,无需调整。如果提取出的是特征2,但是图片的标签是A,那么证明参数不准确,需要调整下参数。调整完参数后继续下次训练,以此类推,直到参数大概率准确的时候。 很简单的去解释了CNN卷积神经网络是怎么工作的,当然实际的过程比这要复杂的多,提取特征需要一些算法,比如卷积、池化、激活,算法的参数也不是1个这么简单,而是几百万个。下面的文章中基于Tensorflow中一个很简单的例子MNIST问题的代码来讲一下CNN网络是怎样工作的。 3. MNIST问题 MNIST问题就相当于图像处理的Hello World程序,在Tensorflow的官方教程里已经有一个完整的Demo。 MNIST问题处理 MNIST问题是很常见的图片分类问题,训练集是已经编码过的手写图片,图片中是手写的0~9的数字,模型经过训练后,输入一张图片,可以输出0~9的数字。 3.1 输入集 首先我们来看一下MNIST问题的输入集,数据集的介绍传送门。 整个数据集由以下四个文件构成, //训练集-图片数据 train-images-idx3-ubyte.gz: training set images (9912422 bytes) //训练集-label数据 train-labels-idx1-ubyte.gz: training set labels (28881 bytes) //测试集-图片数据 t10k-images-idx3-ubyte.gz: test set images (1648877 bytes) //测试集-label数据 t10k-labels-idx1-ubyte.

准确率(Accuracy)、精确率(Precision)、召回率(Recall)、F值(F-Measure)、AUC、ROC的理解

一、准确率、精确率、召回率和 F 值 是选出目标的重要评价指标。不妨看看这些指标的定义先: (1)若一个实例是正类,但是被预测成为正类,即为真正类(True Postive TP) (2)若一个实例是负类,但是被预测成为负类,即为真负类(True Negative TN) (3)若一个实例是负类,但是被预测成为正类,即为假正类(False Postive FP) (4)若一个实例是正类,但是被预测成为负类,即为假负类(False Negative FN) 下表中:1代表正类,0代表负类: TP:正确的匹配数目 FP:误报,没有的匹配不正确 FN:漏报,没有找到正确匹配的数目 TN:正确的非匹配数目 准确率(正确率)=所有预测正确的样本/总的样本 (TP+TN)/总 精确率= 将正类预测为正类 / 所有预测为正类 TP/(TP+FP) 召回率 = 将正类预测为正类 / 所有正真的正类 TP/(TP+FN) F值 = 精确率 * 召回率 * 2 / ( 精确率 + 召回率) (F 值即为精确率和召回率的调和平均值) 二、ROC曲线:接收者操作特征(receiver operating characteristic),roc曲线上每个点反映着对同一信号刺激的感受性。 纵轴:真正类率(true postive rate TPR),也叫真阳性率 横轴:假正类率(false postive rate FPR),也叫伪阳性率 由上表可得出横,纵轴的计算公式: (1)真正类率(True Postive Rate)TPR: TP/(TP+FN), 代表分类器 预测为正类中实际为正实例 占 所有正实例 的比例。

第一部分 第三章 1039-1058 答案合集

1039 判断数正负 #include <iostream> #include <cstdio> using namespace std; int main() { int a; scanf("%d",&a); if(a>0) printf("positive"); if(a==0) printf("zero"); if(a<0) printf("negative"); return 0; } 1040 输出绝对值 #include <iostream> #include <cstdio> using namespace std; int main() { double a; scanf("%lf",&a); if(a>=0) printf("%.2lf",a); else printf("%.2lf",-a); return 0; } 1041 奇偶数判断 #include <iostream> #include <cstdio> #include <cmath> using namespace std; int main() { int a; scanf("%d",&a); if(a%2==1) printf("odd"); else printf("even"); return 0; } 1042 奇偶ASCII值判断

Python学习--QtPy系列2(信号和事件)

事件 所有的GUI应用都是事件驱动的。事件主要由应用的用户操作产生的。但是事件可能由其他条件触发,比如:一个网络连接,一个窗口管理器,一个定时器,这些动作都可能触发事件的产生。当我们调用应用的exec_()方法时,应用进入了主循环。主循环用于检测事件的产生并且将事件送到用于处理的对象中去。 在事件模型,有三个参与者 事件源事件对象事件目标 事件源是状态发生改变的对象。它产生了事件。事件对象(evnet)封装了事件源中的状态变化。事件目标是想要被通知的对象。事件源对象代表了处理一个事件直到事件目标做出响应的任务。 PyQt5有一个独一无二的信号和槽机制来处理事件。信号和槽用于对象之间的通信。当指定事件发生,一个事件信号会被发射。槽可以被任何Python脚本调用。当和槽连接的信号被发射时,槽会被调用。 import sys #系统模块 from PyQt5.QtCore import Qt #Qt模块 from PyQt5.QtWidgets import (QWidget, QLCDNumber, QSlider, QVBoxLayout, QApplication) #导入QWidget, QLCDNumber, QSlider,QVBoxLayout, QApplication等模块 class Example(QWidget): def __init__(self): super().__init__() #继承父类构造函数 self.initUI() #初始化UI def initUI(self): lcd = QLCDNumber(self) sld = QSlider(Qt.Horizontal, self) vbox = QVBoxLayout() vbox.addWidget(lcd) vbox.addWidget(sld) self.setLayout(vbox) sld.valueChanged.connect(lcd.display) self.setGeometry(300, 300, 250, 150) self.setWindowTitle('Signal & slot') self.show() if __name__ == '__main__': app = QApplication(sys.argv) ex = Example() sys.exit(app.exec_()) sld.

树的三种遍历方式源码(递归与非递归)

在面试的时候,我们会经常被问到树的三种遍历,也就是前序遍历、中序遍历和后序遍历。 所谓前序遍历,就是先访问根节点,再左,再右。命名方式就是根据根节点是在哪访问的去定义的。下面我们先用Java实现三种遍历的递归,是非常的简单。 树的前序遍历: public void recursiveProOrder(Node root) { if (root != null) { System.out.print(root.value); if (root.left != null) { recursivePostOrder(root.left); } if (root.right != null) { recursivePostOrder(root.right); } } } 树的中序遍历: public void recursiveInOrder(Node root) { if (root != null) { if (root.left != null) { recursiveInOrder(root.left); } System.out.print(root.value); if (root.right != null) { recursiveInOrder(root.right); } } } 树的后序遍历: public void recursivePostOrder(Node root) { if (root != null) { if (root.

如何把Matlab图像输出为高分辨率格式

在matlab中画完图,经常希望输出的图像清晰一些,分辨率高一些,以前一直在用file–>save as–>选择tif格式,然后点击确定。这样输出的图像清晰度是默认的,可能不能满足所需要的清晰度。 要想输出清晰度的图像,步骤如下: File–>export setup,显示如下图所示对话框,然后点击Rendering,里面选择resolution,修改为600,点击export,选择输出格式,OK,即可。 参考怎样使Matlab图片放在Word中最清晰?

MAC 开启80端

这并非一个非常难的问题,但是可以去百度,得到的答案真的五花八花。 那我们今天就来解决这个问题。 1、首先需要谁占用了端口。点击打开链接 可以看出是mac自带的apche占用了80端口,所以需要停止apche,并修改配置文件 2、停止apche sudo apachectl stop 3、修改apache的端口 sudo vi httpd.conf 找到listen 80,修改掉。 这样80端口就可以用了。

SQL Server(MSSQLSERVER)无法启动怎么解决?

1、IP地址配置不正确: 打开 Microsoft SQL Server 2005配置工具下的SQL Server Configuration Manager,选择MSSQLSERVER协议, 然后双击右边窗口的TCP/IP,在弹出窗口中检查IP配置。 2、可能是因为VIA协议启用造成的。解决方法如下: 打开SQL Server 2008中的配置工具SQL Server Configure Manager,将VIA协议禁用.重新启动SQL Server(MSSQLSERVER ),成功. 3、管理员密码修改也会造成sqlserver服务无法启动。解决方法如下: 打开 Microsoft SQL Server 2005配置工具下的SQL Server Configuration Manager,在MSSQLSERVER服务属性中,修改以哪个账号来启动服务。我机器启动不了服务的原因就是启用了 “VIA”服务,禁用后,OK了。 安装的是SQL Server 评估版,180天的试用期后,MSSQLSERVER服务就无法启动,手动启动就报告17051错误。 解决办法:第一步:进入SQL2008配置工具中的安装中心,第二步:再进入维护界面,选择版本升级,第三步:进入产品密钥,输入密钥Developer: PTTFM-X467G-P7RH2-3Q6CG-4DMYBEnterprise: JD8Y6-HQG69-P9H84-XDTPG-34MBB第四步:一直点下一步,直到升级完毕。 用key升级成功后即可启动MSSQLSERVER服务。如果启动SQL SERVER管理器依然报告过期错误,则将注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\100\ConfigurationState,将其中CommonFiles的键值改为3。然后再重复以上四个步骤,进行升级就OK了。

MySQL 5.5 安装

如果以前安装过,卡在最后一步,请先将原来的MySQL服务停止 1添加删除程序中卸载MySQL 2到安装目录删除MySQL 3删除:C:\Documents and Settings\All Users\Application Data目录下的MySQL目录 C:\ProgramData目录下的MySQL目录 4查看注册表: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Services 搜索mysql,找到一律干掉! ============================ 不需要重启电脑(win xp),直接重新安装即可,卸载,重新安装, 校验: 2 校验MySQL 登录MySQL:mysql -uroot -p123 退出MySQL:exit | quit 查看数据库:show databases; 二. 安装MySQL客户端工具sqlyog82 1:安装sqlyog82.exe 2:用户名:oyksoft 注册码:26f359fc-e3f6-4727-8af1-72a1a4a0819d

android ViewPager与ScrollView滑动冲突解决

内部解决法: 重写ViewPager的dispatchTouchEvent方法判断滑动倾向 import android.content.Context; import android.support.v4.view.ViewPager; import android.util.AttributeSet; import android.view.MotionEvent; public class HorizontalViewPager extends ViewPager { int lastX = -1; int lastY = -1; public HorizontalViewPager(Context context) { super(context); } public HorizontalViewPager(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { int x = (int) ev.getRawX(); int y = (int) ev.getRawY(); int dealtX = 0; int dealtY = 0; switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: getParent().requestDisallowInterceptTouchEvent(true); break; case MotionEvent.

网关地址设置

1、网关地址是具有网络路由转发功能的设备的IP地址; 2、一般默认网关地址设置为xx.xx.xx.254; 3、如果一个网段被分成了多个VLAN子网,那么每个VLAN都需要一个网关,需要在交换机上设置网关IP地址。 具体的网关IP地址没有特别限制,根据实际情况设置。 转载于:https://www.cnblogs.com/FarmPick/p/9002640.html

C++ vector、string使用

vector就是类似于一个数组的容器,内容比数组更加全面。很多操作都有自己的函数可以直接拿过来进行使用。主要函数就是: v.push_back(k); 尾插元素;v.insert(it,k); 在任意位置插入元素;v.eraser(it,it+k); 删除任意元素;v.size(); 容量;v.clear(); 清空容器;v.empty(); 判断容器是否为空;reverse(v.begin(),v.end());反转任意段元素sort(v.begin(),v.end(),cmp);sort排序默认由小到大,cmp可以自由规定排序规则。 迭代器声明: vector<int>::iterator it;// vector迭代器 #include <iostream> #include <vector> #include <string> #include <algorithm> using namespace std; bool cmp(const int &a,const int &b){ return a>b; } int main () { set<int> c; queue<int> q; cout<<"------------[vector] 分割线-------------\n"<<endl; vector<int> v(1); v[0]=0; v.push_back(1); // 尾插元素 v.push_back(2); v.push_back(3); v.push_back(4); v.insert(v.begin(),55); // 插入元素 v.insert(v.begin()+1,66); vector<int>::iterator p; // vector迭代器 for(p=v.begin();p!=v.end();p++) cout<<*p<<" "; cout<<endl; cout<<v.size()<<endl; // vector元素个数 reverse(v.begin(),v.end()); // 反转vector sort(v.

北航 机试 小岛面积

小岛面积 1 1 1 1 1 1 1 1 0 0 0 1 1 0 0 0 1 0 1 1 0 1 1 1 0 1 0 1 0 0 1 1 1 1 1 1 上面矩阵的中的 1 代表海岸线,0 代表小岛。求小岛面积(即被 1 中包围的 0 的个数)。注意: 仅求这样的 0,该 0 所在行中被两个 1 包围,该 0 所在列中被两个 1 包围。 输入: 第一行输入一个整数 N,表示输入方阵的维数 输入一个 N 维方阵 输出: 小岛面积 样例输入: 6 1 1 1 1 1 1 1 1 0 0 0 1 1 0 0 0 1 0 1 1 0 1 1 1 0 1 0 1 0 0 1 1 1 1 1 1 样例输出: 8

java中什么是方法以及方法怎么定义

我们先来理解一下什么叫做方法,通俗一点来说: 在我们的日常生活中,方法可以理解为要做某件事情,而采取的解决办法。 如:小明同学在路边准备坐车来学校学习。这就面临着一件事情(坐车到学校这件事情)需要解决,解决办法呢?可采用坐公交车或坐出租车的方式来学校,那么,这种解决某件事情的办法,我们就称为方法。 在java中,方法就是用来完成解决某件事情或实现某个功能的办法。 方法实现的过程中,会包含很多条语句用于完成某些有意义的功能——通常是处理文本,控制输入或计算数值。 我们可以通过在程序代码中引用方法名称和所需的参数,实现在该程序中执行(或称调用)该方法。方法,一般都有一个返回值,用来作为事情的处理结果。 方法的语法格式 在Java中,声明一个方法的具体语法格式如下 修饰符 返回值类型 方法名(参数类型 参数名1,参数类型 参数名2,......){ 执行语句 ……… return 返回值; } 对于上面的语法格式中具体说明如下: 1)修饰符:方法的修饰符比较多,有对访问权限进行限定的,有静态修饰符static,还有最终修饰符final等,这些修饰符在后面的学习过程中会逐步介绍 2)返回值类型:用于限定方法返回值的数据类型 3)参数类型:用于限定调用方法时传入参数的数据类型 4)参数名:是一个变量,用于接收调用方法时传入的数据 5)return关键字:用于结束方法以及返回方法指定类型的值 6)返回值:被return语句返回的值,该值会返回给调用者 需要特别注意的是,方法中的“参数类型 参数名1,参数类型 参数名2”被称作参数列表,它用于描述方法在被调用时需要接收的参数,如果方法不需要接收任何参数,则参数列表为空,即()内不写任何内容。方法的返回值必须为方法声明的返回值类型,如果方法中没有返回值,返回值类型要声明为void,此时,方法中return语句可以省略。 接下来通过一个案例来演示方法的定义与使用,如下。 public class Method { public static void main(String[] args) { int area = getArea(3, 5); // 调用 getArea方法 System.out.println(" The area is " + area); } // 下面定义了一个求矩形面积的方法,接收两个参数,其中x为高,y为宽 public static int getArea(int x, int y) { int temp = x * y; // 使用变量temp记住运算结果 return temp; // 将变量temp的值返回 } } 在上述代码中,定义了一个getArea()方法用于求矩形的面积,参数x和y分别用于接收调用方法时传入的高和宽,return语句用于返回计算所得的面积。在main()方法中通过调用getArea()方法,获得矩形的面积,并将结果打印。

Window mysql 5.7 忘记root密码

1、命令行: mysqld -nt --skip-grant-tables 2、新打开CMD窗口 mysql -uroot update user set authentication_string=password('root') where user='root'; flush privileges; 3、关掉所有CMD窗口,重启Mysql服务 4、如果使用客户端登陆,显示密码过期,解决办法如下: 4.1、使用CMD登陆数据库(CMD使用密码登陆不会过期的) 4.2、输入命令: set password = password('root');

InnoDB索引最通俗的解释

什么是索引 索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分)内部数据结构使用的B+树,B树节点内部包含着对数据表里所有记录的引用指针。更通俗的说,数据库索引好比是一本书前面的目录,能加快数据库的查询速度。上述SQL语句,在没有索引的情况下,数据库会遍历全部数据后选择符合条件的;而有了相应的索引之后,数据库会直接先在索引中查找符合条件的选项。如果我们把SQL语句换成“SELECT * FROM article WHERE id=2000000”,那么你是希望数据库按照顺序读取完200万行数据以后给你结果还是直接在索引中定位呢?(注:一般数据库默认都会为主键生成索引)。 树 二叉查找树(Binary Search Tree),平衡二叉查找树(Balanced Binary Search Tree),红黑树(Red-Black Tree ),B-tree和B+-tree。前三者是典型的二叉查找树结构,其查找的时间复杂度O(log2N)与树的深度相关,那么降低树的深度自然会提高查找效率。 二叉查找树:左子树键值总是小于根的键值,右子树键值总是大于根的键值。因此中序遍历可以得到键值的排序输出。 上述中序输出就是:2 3 5 6 7 8。 但是二叉查找树可以以任意的顺序插入,例如当数据2 3 5 6 7 8以有序的顺序插入时候,树的结构就是下图: 可以看到树已经出现了极度不平衡,查找速度一定和线性查找一样了。为了解决上述问题,出现了后续的树种。 平衡二叉树:为了提高二叉树的搜索的效率,减少树的平均搜索长度,提出了AVL树,它的左子树和右子树的深度之差(平衡因子)的绝对值不超过1(也就是高度的平衡),且它的左子树和右子树都是一颗平衡二叉树。为了维持高度的平衡,则频繁的插入和删除,会引起频繁的reblance(旋转以维持平衡),导致效率可能会下降。具体代码如何编写,暂不考虑,因为每什么用。 红黑树:红黑树,一种二叉查找树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树牺牲了绝对平衡,换取了少旋转。红黑树确保没有一条路径会比其他路径长出俩倍,且对于任意结点而言,其到叶结点树尾端NIL指针的每条路径都包含相同数目的黑结点,因而是接近平衡的。 红黑树不是高度平衡的,算是一种折中,插入最多两次旋转,删除最多三次旋转。很好的解决了平衡二叉树旋转次数出现很多的可能。 红黑树具有5个性质: 每个结点要么是红的要么是黑的。 根结点是黑的。 每个叶结点(叶结点即指树尾端NIL指针或NULL结点)都是黑的。 如果一个结点是红的,那么它的两个儿子都是黑的。 对于任意结点而言,其到叶结点树尾端NIL指针的每条路径都包含相同数目的黑结点。 正是红黑树的这5条性质,使一棵n个结点的红黑树始终保持了logn的高度,从而也就解释了上面所说的“红黑树的查找、插入、删除的时间复杂度最坏为O(log n)。具体如何插入、查找、删除,就根本不需要考虑了,实现起来相当的复杂。 B树:B树又叫做多叉平衡查找树。前面的平衡二叉树分支最多有2个,但是这里的B树分支可以有n个。分支多的好处就会形成一个矮胖矮胖的平衡二叉树。每个节点里面含有许多个键-值对。这就是B树。 B树中的每个结点根据实际情况可以包含大量的关键字信息和分支(当然是不能超过磁盘块的大小,根据磁盘驱动(disk drives)的不同,一般块的大小在1k~4k左右);这样树的深度降低了,这就意味着查找一个元素只要很少结点从外存磁盘中读入内存,很快访问到要查找的数据。 上述就是一个B树。 外部存储不同于内存的主要特性就是需要花费很多的时间去定位特定的页,但是页读取数据非常快。所以需要使用最少的时间来定位到相应的页。 对于在外存储器-磁盘上面的数据使用这种树,可以最大程度的减少IO操作。 B+树:是B树的变体。B+-tree的内部结点并没有指向关键字具体信息的指针,只有在叶子节点才会有每个关键字具体信息,且每个节点内部含有键值的冗余。因此其内部结点相对B树更小。如果把所有同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存中的需要查找的关键字也就越多。相对来说IO读写次数也就降低了。 如上是一颗B+树,除了叶子节点之外节点内部仅仅含有键而已。到了最后叶子节点里面才含有每个键对应的值(指针指向关键信息)信息。 B+树特点: 所有的叶子结点中包含了全部元素的信息,及指向含这些元素记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接。所有的中间节点元素都同时存在于子节点,在子节点元素中是最大(或最小)元素。 B+树的优点: 单一节点存储更多的元素(因为不含有对应的值,仅仅含有键),使得查询的IO次数更少。所有查询都要从根节点查找到叶子节点,查询性能稳定,相对于B树更加稳定,以为B+树只有叶子节点存储了对应的值信息。所有叶子节点形成有序双向链表,对于SQL的范围查询以及排序查询都很方便。B/B+树的共同优点的每个节点有更多的孩子,插入不需要改变树的高度,从而减少重新平衡的次数,非常适合做数据库索引这种需要持久化在磁盘,同时需要大量查询和插入的应用。树中节点存储这指向页的信息,可以快速定位到磁盘对应的页上面。 InnoDB索引实现 B+树索引并不能找到一个给定键值的具体行。B+树索引能找到的只是被查找数据行所在的页。然后数据库通过把页读入到内存,再在内存中进行查找,最后得到要在找的数据。因为页目录中的槽是按照主键顺序排列的,所以在每一个页目录中,通过二分查找,定位到数据行所在的页,然后将整个页读入内存,进而将整个页中的单向链表遍历得到相应的行数据。下面几个链接中文章仔仔细细的详述了这中思维。 InnoDB记录存储结构 InnoDB数据页结构 MySQL的索引实现 总结 1、对于InnoDB存储引擎来说,在单个页中查找某条记录分为两种情况: 以主键为搜索条件,可以使用Page Directory通过二分法快速定位相应的用户记录。以其他列为搜索条件,需要按照记录组成的单链表依次遍历各条记录。 2、没有索引的情况下,不论是以主键还是其他列作为搜索条件,只能沿着页的双链表从左到右依次遍历各个页。 3、InnoDB存储引擎的索引是一棵B+树,完整的用户记录都存储在B+树第0层的叶子节点,其他层次的节点都属于内节点,内节点里存储的是目录项记录。InnoDB的索引分为两大种: 聚簇索引:以主键值的大小为页和记录的排序规则,在叶子节点处存储的记录包含了表中所有的列。二级索引或叫做辅助索引:以自定义的列的大小为页和记录的排序规则,在叶子节点处存储的记录内容是列内容 + 主键。二级节点查找需要查找二级节点B+树,然后再查看聚集索引B+树中叶子节点对应的记录内容。 4、MyISAM存储引擎的数据和索引分开存储,这种存储引擎的索引全部都是二级索引,在叶子节点处存储的是列 + 页号。

Lsyncd:负载均衡之后,服务器的文件双向同步

场景描述: 在 Linux 服务器上,通过使用 Nginx 实现负载均衡,或者在阿里云直接购买负载均衡,根据配置的转发规则,不同的请求会被转发到其不同的服务器上进行处理。如果遇到需要上传图片的情况,那最后只有其中一台服务器存有这张图片,而其他服务器则没有。随后,如果请求获取这张图片,但是转发到的恰好是没有存有这张图片的服务器,那么请求就失败了。为了避免这类问题,就需要同步相应的目录上的文件。 Lsyncd 简述: Lsyncd 是一个简单高效的文件同步工具,通过lua语言封装了 inotify 和 rsync 工具,采用了 Linux 内核(2.6.13 及以后)里的 inotify 触发机制,然后通过rsync去差异同步,达到实时的效果。 安装过程: 1、安装 lua 语言依赖包 yum install lua yum install lua-devel 2、安装 Lsyncd yum install lsyncd 这里一定要注意,最好安装最新的版本,笔者安装的版本是 2.2.2 。网上很多教程的版本是2.1.5 ,这个版本有 bug ,但在后续的版本里已经修复,直接安装即可。之后,你可以发现在 etc 目录下,不但多了 lsyncd.conf 配置文件,而且还多了 rsync 工具的配置文件 rsyncd.conf 。这说明 Lsyncd 工具确是使用 rsync 工具创建起来的,通过 rsync 去进行目录的差异同步。 远程前提: 通过 Lsyncd 工具同步负载均衡转发规则下的服务器,需要在涉及的服务器上都安装好 Lsyncd ,一般通过 SSH 远程登录,进行远程同步。因此,在远端被同步的服务器上开启 SSH 无密码登录,请注意用户身份,将对应的用户 user 公钥 id_rsa.pub 复制到被同步的服务器的 .ssh 文件目录下的 authorized_keys 文件里,最后测试是否可以无密码登陆。

跨时钟域设置set_false_path的问题

问题: 请教下:两个异步时钟域有path, 但是都经过了同步。 应该怎么约束这种异步path? 直接设置成false path 是否可以,为什么好多 ip的这种path 都通过set max delay设置为一个 源时钟域的周期?这样设置是否只为了保证性能, 为什么不设置为两个时钟周期? 回答: 1:两个异步时钟域设置false path是可以的,设置max delay是保证总线类的跨时钟信号在被采样的时候是采的同一拍的数据,约束上一般是目的时钟的一个或者半个周期,最严格的是源和目的的最快时钟周期的一半。 2:异步时钟域如果没有path或者path根本不影响功能,应该直接设置false path就行。 但是如果异步时钟域之间有功能path,并且 这些path经过同步处理,那么如果也只设置成false path,我的理解是这样会影响性能,不影响功能。所以使用set max delay保证性能。 这样理解是否正确? 3: 还是要看你的设计,比如总线跨时钟,假设是3bit信号,如果仅仅设置异步,那么1bit可能是1cycle到达,1bit可能是2cycle到达,还有1bit可能是3cycle到达,这个时候跨时钟采样的就不是源端同一拍的数据,如果设计容忍度很高,比如是静态的,那么没有问题,如果设计容忍度不高,比如只能保持两拍数据不变,那么功能上就可能会出错。: 4:多谢。一般的多bit bus不会直接使用异步时钟采样进行同步的,基本都是fifo,除非向你说的是静态的。 我在多问一下, 比如总线使用异步fifo同步, 约束的时候都会约束下异步fifo中的格雷码信号, 设置为set_max_delay $source_clk_period, 这样是否仅仅是为了保证性能,即 如果异步fifo中的格雷码同步信号path直接设置为false path不会影响功能,只是影响性能? 5:如果只set_false_path, 那么综合工具不会把对应的CDC路径看成所谓的“timing path”,会认为“这条路径的timing无所谓”,会可能预先插入很多不必要的cell。更重要的是,当后端的人实际layout的时候,也会认为这是false path,因此可能会因为芯片P/R空间不够,或者走线不够balance, 或者局部power没法收敛等等原因,最终把所关注的这些CDC path拉的很长或者很散,甚至能在layout里面走多层或者对角线。你可以在相关的PT setup timing report里会见到drive强度很大(比如D16,D32 etc)的一坨BUF,或冷不丁蹦出几个延时很长(好几百ps)的delay cell。对于false path,会导致工具理解设计时有误,因此才用set_max_delay做显式的延时约束

关于vs2017中无法下载win10SDK

①: ②: 错误现象:所有的程序编译都会有460个错误,说是什么无法加载包含文件什么的 解决方法:下载独立的win10SDK win10SDK下载网址 https://developer.microsoft.com/zh-cn/windows/downloads/windows-10-sdk

图的MST(最小生成树算法)Kruskral+Prim

##前言 文章记录数据结构中求最小生成树的两种经典算法:Kruskal和Prim算法。 ##Kruskal算法 算法的实现步骤: 个人理解: 将图中所有的带权边按照权值大小(从小到大的次序)依次排序;形如<2,5>:3;<2,3>:4等,表示结点2到结点5能够连通,路径长度为3。从上按照从小到大的‘顶点边权列表’中依次选择边权值最小且不构成环路的这些边形成最小生成树。 老师给的步骤: 将所有的边按权值排序;设每个顶点为一个独立的点集,生成树T为空集;依序扫描每一条边,直到已输出n-1条边: 若vi、vj均不在同一点集中,则将该边加入生成树T中,并合并这两个点集;否则舍弃该边; 图示辅助理解: 算法的代码实现: #include<iostream> #include<algorithm> #define maxv 101 #define maxe 100 using namespace std; int r[maxe]; int p[maxv]; int u[maxv],v[maxv],w[maxv]; int n,m; int cmp(const int i,const int j) { return w[i]<w[j]; } int find(int x) { return p[x]==x?x:p[x]=find(p[x]); } int Kruskal(int u[maxv],int v[maxv],int w[maxv],int n,int m) { int ans=0; //循环设置每一个顶点序号 for(int i=0;i<n;i++) p[i]=i; for(int i=0;i<m;i++) r[i]=i; sort(r,r+m,cmp); /* cmp 为sort函数中的排序规则 其中的常量 i j 表示待排序中的两个变量 return 后的内容表示排序的规则 w[i]<w[j] 按照 w 权值的大小进行排序 比较结果为真返回 1 否则返回 0 */ //排序后 边权 //for(int i=0;i<m;i++) // cout<<"

条件变量(Condition Variable)详解

http://www.wuzesheng.com/?p=1668 条件变量(Condtion Variable)是在多线程程序中用来实现“等待->唤醒”逻辑常用的方法。举个简单的例子,应用程序A中包含两个线程t1和t2。t1需要在 bool变量test_cond为true时才能继续执行,而test_cond的值是由t2来改变的,这种情况下,如何来写程序呢?可供选择的方案有两 种: 第一种是t1定时的去轮询变量test_cond,如果test_cond为false,则继续休眠;如果test_cond为true,则开始执行。第二种就是上面提到的条件变量,t1在test_cond为false时调用cond_wait进行等待,t2在改变test_cond的值后,调用cond_signal,唤醒在等待中的t1,告诉t1 test_cond的值变了,这样t1便可继续往下执行。 很明显,上面两种方案中,第二种方案是比较优的。在第一种方案中,在每次轮询时,如果t1休眠的时间比较短,会导致cpu浪费很厉害;如果t1休眠的时间 比较长,又会导致应用逻辑处理不够及时,致使应用程序性能下降。第二种方案就是为了解决轮询的弊端而生的。然而条件变量在使用的过程中,比较容易出错,如 何用得不正确的话,会适得其反的,接下来,我将详细分析如何来使用条件变量,希望能够给在使用条件变量过程中遇到问题的朋友有所帮助。在开始介绍之前,需要说明一下,在接下来的介绍中,需要用到互斥锁和条件变量相关的内容,在这里我以linux下的pthread_mutex_t为互斥 锁类型,pthread_cond_t为条件变量类型来进行介绍,对pthread不熟的朋友,可以参考一下linux下的manual。1. 下面是把刚开始举的例子翻译后的程序: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 pthread_mutex_t mutex; ///< 互斥锁 pthread_cond_t cond; ///< 条件变量 bool test_cond = false; /// TODO 初始化mutex和cond /// thread 1: pthread_mutex_lock(&mutex); ///< 1 while (!test_cond) { pthread_cond_wait(&cond, &mutex); ///< 2,3 } pthread_mutex_unlock(&mutex); ///< 4 RunThread1Func(); /// thread 2: pthread_mutex_lock(&mutex); ///< 5 test_cond = true; pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); ///< 6 /// TODO 销毁mutex和cond 通过上面的例子,下面我来介绍一下条件变量在使用过程中需要注意的几点(也是比较容易出错的):(1)条件变量的使用过程中,最为关键的一点是互斥锁的使用。细心的朋友应该发现了,我在上面的例子中标了1、2、3、4、5、6个标号。在这里1、4、 5、6都是正常的lock/unlock,2、3是需要特别说明的。2是进入pthread_cond_wait后 的,pthread_cond_wait调的pthread_mutex_unlock,这样做的目的是为了保证在thread1阻塞wait 后,thread2获取同一把锁mutex的时候,能够正常获取(即5,6)。3是thread1被唤醒后,要退出pthead_cond_wait之 前,pthread_cond_wait调的pthread_mutex_lock,这样做的目的是为了把mutex的控制权还给调用 pthread_cond_wait的线程(即thread1)。整理一下基本的时序为:

springboot项目启动时报A child container failed during start

使用springboot写的项目,启动时报该异常,在网上尝试寻找了很多解决办法,都不行。不过通过看别人的错误原因,大概定位到,这个异常是由于jar包冲突导致的异常。因此把主要精力放在了jar包上面。因为是测试项目启动报错,正式环境没有问题。所以就将报错项目的lib文件夹替换为正式环境的lib。结果问题真的解决了。 具体是那个jar包我并没有去详细找,不过,想提醒自己及有同样错误的朋友,如果出现了这个问题,不妨先看看jar包是否有问题。

链表基础知识总结

链表和数组作为算法中的两个基本数据结构,在程序设计过程中经常用到。尽管两种结构都可以用来存储一系列的数据,但又各有各的特点。 数组的优势,在于可以方便的遍历查找需要的数据。在查询数组指定位置(如查询数组中的第4个数据)的操作中,只需要进行1次操作即可,时间复杂度为O(1)。但是,这种时间上的便利性,是因为数组在内存中占用了连续的空间,在进行类似的查找或者遍历时,本质是指针在内存中的定向偏移。然而,当需要对数组成员进行添加和删除的操作时,数组内完成这类操作的时间复杂度则变成了O(n)。 链表的特性,使其在某些操作上比数组更加高效。例如当进行插入和删除操作时,链表操作的时间复杂度仅为O(1)。另外,因为链表在内存中不是连续存储的,所以可以充分利用内存中的碎片空间。除此之外,链表还是很多算法的基础,最常见的哈希表就是基于链表来实现的。基于以上原因,我们可以看到,链表在程序设计过程中是非常重要的。本文总结了我们在学习链表的过程中碰到的问题和体会。 接下来,我们将对链表进行介绍,用C语言分别实现:链表的初始化、创建、元素的插入和删除、链表的遍历、元素的查询、链表的删除、链表的逆序以及判断链表是否有环等这些常用操作。并附上在Visual Studio 2010 中可以运行的代码供学习者参考。 说到链表,可能有些人还对其概念不是很了解。我们可以将一条链表想象成环环相扣的结点,就如平常所见到的锁链一样。链表内包含很多结点(当然也可以包含零个结点)。其中每个结点的数据空间一般会包含一个数据结构(用于存放各种类型的数据)以及一个指针,该指针一般称为next,用来指向下一个结点的位置。由于下一个结点也是链表类型,所以next的指针也要定义为链表类型。例如以下语句即定义了链表的结构类型。 typedef struct LinkList { int Element; LinkList * next; }LinkList; 链表初始化 在对链表进行操作之前,需要先新建一个链表。此处讲解一种常见的场景下新建链表:在任何输入都没有的情况下对链表进行初始化。 链表初始化的作用就是生成一个链表的头指针,以便后续的函数调用操作。在没有任何输入的情况下,我们首先需要定义一个头指针用来保存即将创建的链表。所以函数实现过程中需要在函数内定义并且申请一个结点的空间,并且在函数的结尾将这个结点作为新建链表的头指针返回给主调函数。本文给出的例程是生成一个头结点的指针,具体的代码实现如下: linklist * List_init() { linklist *HeadNode= (linklist*)malloc(sizeof(linklist)); if(HeadNode == NULL) { printf("空间缓存不足"); return HeadNode; } HeadNode->Element= 0; HeadNode->next= NULL; returnHeadNode; } 当然,初始化的过程或者方法不只这一种,其中也包含头指针存在的情况下对链表进行初始化,此处不再一一罗列。 这里引申一下,此处例程中返回的链表指针为该链表的头结点,相对应的还有一个头指针的概念。头指针内只有指针的元素,并没有数据元素,但头结点除了指针还有数据。 头指针就是链表的名字,仅仅是个指针而已。头结点是为了操作的统一与方便而设立的,放在第一个有效元素结点(首元结点)之前,其数据域一般无意义(当然有些情况下也可存放链表的长度、用做监视哨等等)。一般情况下见到的链表的指针多为头指针,但最近在一个程序员编程网站leetcode中发现,题目中所给的链表一般是首元结点作为第一个元素,而不是头指针。 下图为头指针与头结点以及首元结点的关系。 链表创建 创建链表需要将既定数据按照链表的结构进行存储,本文以一种最简单的方式来演示:使用数组对链表赋值。将原来在连续空间存放的数组数据,放置在不连续的链表空间中,使用指针进行链接。 链表创建的步骤一般使用给定的头指针以及需要初始化的数据序列作为输入参数,本文使用数组作为输入数据序列。在下面的例程中,先将首元结点使用数组第一个元素初始化,再在首元结点之后创建新的链表结点赋值数组内余下的数据。具体实现如下: void CreatList(linklist *HeadNode,int *InData,int DataNum) { int i = 0; linklist *CurrentNode = (linklist*) HeadNode; for(i = 0;i<DataNum;i++) { CurrentNode->Element = InData[i];

单页应用优化--懒加载

单页Web应用(single page web application,SPA)会一次性载入页面资源,利用本地计算能力渲染页面,提高页面切换速度与用户体验。由此带来了首屏加载缓慢耗时的诟病,这也是困扰前端开发工程师的一重大难题。 最近查阅了一些帖子,发现了一个极其强大的方法,其兼容性有待提高~~(但已有相关的的Polyfill方式) 按需加载 // 全部加载 import 'ccharts' // 按需加载 只加载需要使用的组件 import 'echarts/lib/component/title' import 'echarts/lib/component/tooltip' import 'echarts/lib/component/legend' import 'echarts/lib/chart/bar' 可以减小组件加载的大小,节省网络带宽,从而提高响应速度! 异步加载组件 首先我们可以将应用拆成多个模块组件,然后异步加载组件。配合webpack代码分割使用,达到按需加载的效果(下述只简单陈述,不做详细讲解)。 补充,webpack有三种常用的代码分割方式: 入口起点:使用 entry 配置手动地分离代码。防止重复:使用 CommonsChunkPlugin 去重和分离 chunk。动态导入:通过模块的内联函数调用来分离代码。 // 同步方式 import search from '@/views/search/search.vue' // 异步方式 const search = (resolve) => require(['@/views/search.vue'], resolve) // ES6异步方式(推荐) const search = () => import('@/views/search.vue') 注意,webpack中需要配置相关信息 output: { path: '/dist', filename: 'js/[name].[chunkhash].js', chunkFilename:'js/[id].[chunkhash].js' }, 注意,filename决定了bundle的名称。但是此选项不会影响那些「按需加载 chunk」的输出文件。对于这些文件,请使用 output.chunkFilename选项来控制输出。通过 loader 创建的文件也不受影响。在这种情况下,你必须尝试 loader 特定的可用选项。

RandomAccessSource not opened

最近在使用word模板生成pdf,一开始由于一些流没有关闭,导致内存溢出,出现"too many open files",后来就对代码中流和读写对象一通关闭。 代码调整之后,本以为可以完美的解决问题,结果又出现一个莫名的异常“java.io.IOException: RandomAccessSource not opened”,问度娘吧,没有找到合理的解决办法。然后就可以研究代码,从代码上看,真没什么问题啊。 之后就不禁怀疑,是不是哪里的流关早了,还是不该关的流关错了。 从堆栈信息来看,发现异常是打在pdfStamper.close()方法上的, 最后查看代码,在关闭stamper之前,关闭了构建stamper对象的os和reader,如下: 最后将stamper.close()放到最上边,即先关闭stamper,在关闭os和reader,测试一下,完美解决!!!终于可以歇歇了

Unix环境高级编程实验总结

前两周把apue这门课的实验给做完了,base代码是从网上找到的,看着里面有一堆的父子线程的调用就头大,按照实验要求没做的那么复杂,关键是没花时间去做这方面的实验,把进程相关的代码都删掉了,只是添加了一些基本的的类shell命令的函数,又写了一个简单的Makefile,由于最开始的想法是先都添加在一个.c文件中将功能全部都实现,再把函数按照功能一个一个拆分成不同的.c文件,但是往里添加的时候没有标记相关变量和宏是属于哪个头文件,功能都实现之后发现要把相关函数以及他们的头文件拆分出来太浪费时间,真是教训!最后一周做实验,没有那么多的时间,所以为了用Makefile这个装逼lity一点的编译方式而不是gcc这种lame的方式,只好把main.c文件单独拆出,剩下的所有功能得的函数都放在一个.c文件中,勉强做了个Makefile,实在拙劣,有机会再重新弄吧! 一.实验要求: 1.实验目的 理解shell程序的功能。 学会shell的使用。 构造一个简单的shell。 2.实验内容 基本任务:用 C/C++编写一个简单的 Shell 程序,实现以下基本的命令。 1) 浏览目录和文件的各种属性 ls, ls –l 2) 回显 echo 3) 显示文件内容 cat, more ... 4) 创建目录 mkdir 5) 删除目录 rmdir 6) 删除文件 rm 7) 改变目录 cd 8) 改变文件和目录的权限 chmod 9) 显示当前目录 pwd 10) 文字统计wc 11) 查看时间命令 date, time 12) 退出命令exit 13) 发送信号命令kill 14) 查看在线用户who 15) 查看命令历史记录history 16) 执行用户的程序 17) help 功能 选做任务: 提供友好的人机界面; 提供帮助功能; 写一个 makefile 来管理 3. 要求

gradle刷新项目出现Error:Could not run build action using Gradle installation

【日期】2018-05-02 【问题】gradle刷新项目报错Error:Could not run build action using Gradle installation 【原因】 电脑防火墙一般情况下都是关闭状态,前段时间出差把电脑防火墙打开了,gradle在防火墙打开的情况下会运行异常 【发现过程】今天开发gradle项目发现异常,一时意识不到是防火墙问题 【修复】关闭防火墙 【是否我导致】是 【解决Bug的时间】1小时 【教训】涉及联网的工具考虑防火墙影响

win7英文版很多软件中文显示乱码解决方案

在win7英文版下,很多软件中文字体均显示问号,通过如下解决方案,经测试,可以完美解决: 一、通过控制面板->时钟、语言和区域,打开区域和语言面板; 二、修改如下配置: 1、区域和语言->格式->选择“日语”->应用->再选择“中文”->应用; 2、区域和语言->位置->选择“日本”->应用->再选择“中国”->应用; 3、区域和语言->管理->复制设置->勾选“欢迎屏幕和系统账户”->应用,但不要重新启动系统; 4、区域和语言->管理->更改系统区域设置->选择“日语”->应用->选择“中文简体”->应用; 三、以上设置完成后,再重启系统,即可解决中文乱码问题 Control Pannel-->Clock, Language, and Region-->Administrative-->Change system locale-->Select Chinese (PRC) <script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script> 阅读(94) | 评论(0) | 转发(0) | 0 上一篇:从阿里云邮箱迁移至网易邮箱 下一篇:解决linux系统启动之:unexpected inconsistency:RUN fsck 评论热议

如何写一手漂亮的模型:面向对象编程的设计原则综述

选自Medium,机器之心编译。 面向对象的编程在实现想法乃至系统的过程中都非常重要,我们不论是使用 TensorFlow 还是 PyTorch 来构建模型都或多或少需要使用类和方法。而采用类的方法来构建模型会令代码非常具有可读性和条理性,本文介绍了算法实现中使用类和方法来构建模型所需要注意的设计原则,它们可以让我们的机器学习代码更加美丽迷人。 大多数现代编程语言都支持并且鼓励面向对象编程(OOP)。即使我们最近似乎看到了一些偏离,因为人们开始使用不太受 OOP 影响的编程语言(例如 Go, Rust, Elixir, Elm, Scala),但是大多数还是具有面向对象的属性。我们在这里概括出的设计原则也适用于非 OOP 编程语言。 为了成功地写出清晰的、高质量的、可维护并且可扩展的代码,我们需要以 Python 为例了解在过去数十年里被证明是有效的设计原则。 对象类型 因为我们要围绕对象来建立代码,所以区分它们的不同责任和变化是有用的。一般来说,面向对象的编程有三种类型的对象。 1. 实体对象 这类对象通常对应着问题空间中的一些现实实体。比如我们要建立一个角色扮演游戏(RPG),那么简单的 Hero 类就是一个实体对象。 class Hero: def __init__(self, health, mana): self._health = health self._mana = mana def attack(self) -> int: """ Returns the attack damage of the Hero """ return 1 def take_damage(self, damage: int): self._health -= damage def is_alive(self): return self._health > 0 复制代码 这类对象通常包含关于它们自身的属性(例如 health 或 mana),这些属性根据具体的规则都是可修改的。

C++的 RTTI 观念和用途(非常详细)

自从1993年Bjarne Stroustrup 〔注1 〕提出有关C++ 的RTTI功能之建议﹐以及C++的异常处理(exception handling)需要RTTI;最近新推出的C++ 或多或少已提供RTTI。 然而,若不小心使用RTTI,可能会导致软件弹性的降低。本文将介绍RTTI的观念和近况﹐并说明如何善用它。 什么是RTTI﹖ 在C++ 环境中﹐头文件(header file) 含有类之定义(class definition)亦即包含有关类的结构资料(representational information)。但是﹐这些资料只供编译器(compiler)使用﹐编译完毕后并未留下来﹐所以在执行时期(at run-time) ﹐无法得知对象的类资料﹐包括类名称、数据成员名称与类型、函数名称与类型等等。例如﹐两个类Figure和Circle﹐其之间为继承关系。 若有如下指令﹕ Figure *p; p = new Circle(); Figure &q = *p; 在执行时﹐p指向一个对象﹐但欲得知此对象之类资料﹐就有困难了。同样欲得知q 所参考(reference) 对象的类资料﹐也无法得到。RTTI(Run-Time Type Identification)就是要解决这困难﹐也就是在执行时﹐您想知道指针所指到或参考到的对象类型时﹐该对象有能力来告诉您。随着应用场合之不同﹐所需支持的RTTI范围也不同。最单纯的RTTI包括﹕ ●类识别(class identification)──包括类名称或ID。 ●继承关系(inheritance relationship)──支持执行时期的「往下变换类型」(downward casting)﹐亦即动态变换类型(dynamic casting) 。 在对象数据库存取上﹐还需要下述RTTI﹕ ●对象结构(object layout) ──包括属性的类型、名称及其位置(position或offset)。●成员函数表(table of functions)──包括函数的类型、名称、及其参数类型等。 其目的是协助对象的I/O 和持久化(persistence) ﹐也提供调试讯息等。 若依照Bjarne Stroustrup 之建议〔注1 〕﹐C++ 还应包括更完整的RTTI﹕ ●能得知类所实例化的各对象 。 ●能参考到函数的源代码。 ●能取得类的有关在线说明(on-line documentation) 。 其实这些都是C++ 编译完成时所丢弃的资料﹐如今只是希望寻找个途径来将之保留到执行期间。然而﹐要提供完整的RTTI﹐将会大幅提高C++ 的复杂度﹗ RTTI可能伴随的副作用 RTTI最主要的副作用是﹕程序员可能会利用RTTI来支持其「复选」(multiple-selection)方法﹐而不使用虚函数(virtual function)方法。 虽然这两种方法皆能达到多态化(polymorphism) ﹐但使用复选方法﹐常导致违反著名的「开放╱封闭原则」(open/closed principle) 〔注2 〕。反之﹐使用虚函数方法则可合乎这个原则.

snprintf总结

一、函数概要 snprintf函数是sprintf函数的安全版本,因为它在调用的时候需要指定缓冲区的最大尺寸,这样可以有效避免缓冲区的益处。 如果写入的字符串尺寸大于size-1,那么后边的字符串将被丢弃,但是依旧会统计进长度中(返回值)。 format参数后边的额外参数数量是由format决定的,具体用法请参考printf函数中格式化占位符的解释。 将可变个参数(...)按照format格式化成字符串,然后将其复制到str中 (1) 如果格式化后的字符串长度 < size,则将此字符串全部复制到str中,并给其后添加一个字符串结束符('\0'); (2) 如果格式化后的字符串长度 >= size,则只将其中的(size-1)个字符复制到str中,并给其后添加一个字符串结束符('\0') 函数返回值:若成功则返回欲写入的字符串长度,若出错则返回负值。 -------------------------------------------- 函数说明:最多从源串中拷贝n-1个字符到目标串中,然后再在后面加一个0。所以如果目标串的大小为n 的话,将不会溢出。 二、函数原型 #include<stdio.h> int snprintf(char *str, size_t size, const char *format, ...); 三、参数解析 参数含义str指向存放结果字符串的缓冲区size 1.限定缓冲区最大可写入的字节数 2.字符串最多可以拥有size-1 个字符串,最后一个空位用于存放‘\0' 3.size_t 被定义为无符号整型format格式化字符串 ... 可选参数,具体请参考printf函数文档 四、返回值 如果指定size的缓冲区足够存放写入的字符,返回值是实际写入的字符数(不包含表示字符串结束的‘\0’); 如果函数调用失败,返回值是一个负数。 五、功能 :合并字符串、整形变量转换成字符串 (1)将数字变量转换为字符串。 (2)得到整型变量的16进制和8进制字符串。 (3)连接多个字符串。 六、注意 1.试图写入字符的数量超过size,并不会导致错误发生,只是超过部分被丢弃。 2.只有当返回值小于size 且非负数,才证明字符串被完全写入。 举例: 1、整型数字转换为字符串 #include<stdio.h> int main() { char testdstchar[10]={0}; int j = 12; snprintf(testdstchar,sizeof(testdstchar), "%d", j); printf("%s",testdstchar); return 0; } 输出:12

Redis单机模式搭建

Redis在3.0之前只有单机模式,并没有集群模式,所以这里选择2.8版本进行测试 搭建步骤: 1. 上传解压redis root@hadoop01 ~]# mv redis-2.8.18 /opt/software/ (移动到软件目录好管理) 2. 下载gcc,tcl 命令编译器 yum -y install gcc tcl (要使用redis服务器必须得有一个叫做gcc的编译器支持,还得有一个语言支持叫tcl) 3. 找到redis目录下可以看到有个Makefile命令 (编译、创建目录、拷贝make && make PREFIX=/opt/software/redis install) 这个操作完成后,相当于把redis启动程序拷贝到/opt/software/redis目录下了 4. 配置redis环境变量 配置完记得重新加载 . /etc/profile 5. 安装redis服务(/opt/software/redis-2.8.18/utils目录下) Welcome to the redis service installer This script will help you easily set up a running redis server # 如果不用默认配置 , 需要手动输入端口号 , 我们这里就用默认端口 ,按 按 Enter Please select the redis port for this instance: [6379]

Windows远程连接阿里云服务器(Windows版)以及通过公网IP访问

今天打算在阿里云服务器测试一下node,这就需要在自己的电脑桌面远程链接阿里云服务器了。 我用的是Windows版本的阿里云服务器。特此记录一下过程。 首先,打开服务器,找到已经创建好的服务器实例并点击。(购买之后会自动创建的) 之后会跳转到实例页面,点击右侧的“管理” 然后配置安全组。安全组中就是设置哪些IP可以访问我们的服务器。 然后在安全组配置规则。 添加新规则。 如图,想要让Windows电脑远程链接服务器需要开放3389端口,Linux则是要开放22端口。不然就无法用自己的电脑远程链接服务器了。 而想要让公网IP被访问到,则需要监听并开放对应的端口,不然别人是无法通过公网IP访问我们的网站的。 此处我就开放了80和8080端口。 配置完成好之后最好重启一下。。。忘了截图了 在“管理”的右边有一个更多,里面就有重启。。。去找一下吧。 之后就可以用自己的电脑远程连接使用服务器了。 然后用node监听0.0.0.0:8080即可。这样就可以通过公网IP访问了。

iOS 按钮的单选与多选

/** 单选按钮选中*/ @property (nonatomic,strong) UIButton *selectedBtn; - (void)moneybtnClick:(UIButton *)button { // 多选 button.selected = !button.selected; // 单选 if (button!= self.selectedBtn) { self.selectedBtn.selected = NO; button.selected = YES; self.selectedBtn = button; }else{ self.selectedBtn.selected = YES; } }

LeetCode:Rotate Array(旋转数组)

题目 Given an array, rotate the array to the right by k steps, where k is non-negative. Example 1: Input: [1,2,3,4,5,6,7] and k = 3 Output: [5,6,7,1,2,3,4] Explanation: rotate 1 steps to the right: [7,1,2,3,4,5,6] rotate 2 steps to the right: [6,7,1,2,3,4,5] rotate 3 steps to the right: [5,6,7,1,2,3,4] Example 2: Input: [-1,-100,3,99] and k = 2 Output: [3,99,-1,-100] Explanation: rotate 1 steps to the right: [99,-1,-100,3] rotate 2 steps to the right: [3,99,-1,-100] Note: Try to come up as many solutions as you can, there are at least 3 different ways to solve this problem.

第六章 预处理器

第六章 预处理器 《C陷阱与缺陷》学习笔记posts 第六章 预处理器 导读6.1 不能忽视宏定义中的空格6.2 宏并不是函数 6.2.1 括号预防优先级问题6.2.2 避免参数副作用6.3 宏并不是语句宏并不是类型定义总结 导读 预处理器使得编程者可以简化某些工作,它的重要性可以由两个主要的原因说明。 第一,有时候我们希望将某个特定数量(如数据表的大小)在程序中出现的所有实例统统加以修改。只要改一个地方,其他所有地方都修改。第二,C语言函数调用时都会带来巨大的系统开销。因此,我们希望有这样一种程序块,它看上去像一个函数,但却没有函数调用。比如,getchar和putchar经常被实现为宏,宏的作用非常强大,有时候可以使代码看起来更加容易理解,将数字或符号替换为自己熟悉的命名。 6.1 不能忽视宏定义中的空格 宏也是有参数的,和函数一样。函数有空格无关紧要,但是如果宏定义带了空格意思就不一样了。 比如 1.#define f (x) ((x) - 1) 可能观察不仔细的人会以为是将f(x)替换成((x) - 1),这样编译通过不了!所以必须要像下面这样写: 1.#define f(x) ((x) - 1) 这一规则不适用与宏调用,只对宏定义有用。因此,在上面完成宏定义后,f(3)与f (3)求值后都等于2。 6.2 宏并不是函数 6.2.1 括号预防优先级问题 宏严格来说并不是函数,但是很多程序员都喜欢把一些简单的函数定义为宏。比如如下写法: 1.#define abs(x) (((x) >= 0) ? (x) : -(x)) 2.#define max(a,b) ((a) > (b) ? (a) : (b)) 之所以这么多括号是预防引起优先级有关的问题,如果没有括号可能会造成优先级的问题。因为宏不像函数,宏只是起到了一个替换的作用,直接将define的中间替换为后面的表达式。比如 1.#define abs(x) x>0?x:-x 2.abs(a-b); // 会被展开为 a-b>0?a-b:-a-b,其中的-a-b相当于(-a)-b,而不是想象中的-(a-b)。所以最好用括号括起来。 6.2.2 避免参数副作用 在用到类似的三元运算符宏定义#define max(a,b) a>b ?

intellij idea for mac连上不https的SVN解决方式

刚刚开始使用mac系统很多不熟悉,在使用intellij idea自身集成的subversion配置svn库时遇到了无法连接的情况。 找了各种方法发现时mac自身的svn对证书限制的问题所以需要在终端进行连接信任证书,方法如下: 在终端输入 svn list https://svn地址 出现 Error validating server certificate for ‘https://192.168.2.126:443‘: - The certificate is not issued by a trusted authority. Use the fingerprint to validate the certificate manually! - The certificate hostname does not match. Certificate information: - Hostname: Keeasy - Valid: from Tue, 05 Nov 2013 05:48:59 GMT until Fri, 03 Nov 2023 05:48:59 GMT - Issuer: Keeasy - Fingerprint: 43:23:71:ca:b2:44:f6:6d:31:43:cb:ee:65:3b:a6:65:12:1d:2e:e6 (R)eject, accept (t)emporarily or accept (p)ermanently?

在ubuntu上安装多个版本的CUDA,并且可以随时切换

CUDA是什么就不介绍了,直接讲怎么实现CUDA多版本的共存和实时切换。 1、安装多个版本的CUDA 这里,我们以cuda9-1版本和cuda9-0版本为例(先安装哪个无所谓) 首先,在cuda版本库中选择自己需要的cuda版本。 然后,选择对应的安装包,这里选择runfile类型的安装文件,以便后面设置每个cuda的安装路径。 下载完成以后,我们利用cd命令,进入到cuda_8.0.61_375.26_linux.run文件所在的目录中,然后运行下面的指令,进行安装(注意这个文件名,前面的cuda_8.0.61代表cuda的版本,后面的375.26代表的对应的NVIDIA驱动的版本,这里我用cuda8.0的安装过程为例,9.0和9.1同理) 安装过程中在建立软链接时需要注意一下,如果你是第一次安装cuda,那么毫无疑问输入y(yes),但是如果你是安装额外版本的cuda,是否选择y(yes)就要看你的具体需求而定,简言之,就是如果你希望启用当前安装的cuda版本,就选y,如果你只是想安装这个版本,而暂时还不想启用该版本时,就选n。 #先执行下面的命令安装相关依赖, #否则会出现`Missing recommended library`错误 sudo apt-get install freeglut3-dev build-essential libx11-dev libxmu-dev libxi-dev libgl1-mesa-glx libglu1-mesa libglu1-mesa-dev sudo sh cuda_8.0.61_375.26_linux.run #开始安装 #..一堆协议说明... #直接按q退出协议说明. zerozone@zerozone: accept/decline/quit: accept #接受协议 Install NVIDIA Accelerated Graphics Driver for Linux-x86_64 375.26? y)es/(n)o/(q)uit: n #是否显卡驱动包,由于已经安装显卡驱动,选择n Install the CUDA 8.0 Toolkit? (y)es/(n)o/(q)uit: y #是否安装工具包,选择y Enter Toolkit Location [ default is /usr/local/cuda-8.0 ]: #工具包安装地址,默认回车即可 Do you want to install a symbolic link at /usr/local/cuda?

解决移动端position:fixed随软键盘移动的问题

为了让确认按钮固定在屏幕下方,所以按钮框添加样式:{position:fixed;bottom:0} 可是在输入的时候,样式会有问题: 下方按钮跟随软键盘上移了! 这还好手机本身调试不小,不然很有可能连输入框都被挤到上边看不见了。 所以必须对按钮进行控制。 两个方案: 1、当输入框获得焦点时,重新修改按钮样式:{position,'static'},当输入框获得焦点时,样式恢复。 2、与上思路相同,只不过修改的是display属性(反正出现的软键盘也会把按钮覆盖,即使可见也用不了,所以设置为不可见也是不影响的) 这是展示一下方案1的代码: $(输入框).bind('focus',function(){ $('按钮').css('position','static'); }).bind('blur',function(){ $('按钮').css({'position':'fixed','bottom':'0'}); }); 实现效果:

servlet2接收servlet1通过form提交的post请求数据,结果获取的数据中文乱码,使用req.setCharacterEncoding("UTF-8");不管用

public class LoadEmpServlet( servlet1) extends HttpServlet{ private static final long serialVersionUID = 1L; public void service(HttpServletRequest req,HttpServletResponse res) throws IOException{ req.setCharacterEncoding("UTF-8"); res.setContentType("text/html;charset=utf-8"); PrintWriter pw=res.getWriter(); //获取请求参数id int id=Integer.valueOf(req.getParameter("id")); //根据参数id查询数据库获取员工信息 Connection conn=null; PreparedStatement ps=null; ResultSet rs=null; try { Class.forName("com.mysql.jdbc.Driver"); conn=DriverManager.getConnection("jdbc:mysql://localhost:3308/test", "root", "root"); ps=conn.prepareStatement("select * from sysuser where id=?"); ps.setInt(1, id); rs=ps.executeQuery(); pw.println("<html><head></head><body style='font-size:30px'>"); if(rs.next()){ String name=rs.getString("name"); double salary=rs.getDouble("salary"); int age=rs.getInt("age"); pw.println("<form action='modify'> method='post'"); pw.println("编号:"+id+"<br>"); pw.println("<input type='hidden' name='id' value='"+id+"'/><br>"); pw.println("姓名:<input name='name' value='"+name+"'/><br>"); System.

Hystrix核心篇-滑动窗口基础

前言 RxJava可能有些小伙伴没有听过是什么东西,可能是因为大家平时在做业务需求的时候对异步编程了解得比较少,而RxJava就是这么一个响应式编程框架,RxJava在安卓上面用得非常多,做安卓的朋友肯定对它很熟悉。那我这里为什么要讲这个呢?因为spring cloud中服务治理框架Hystrix中大量用到了RxJava的响应式编程,为了便于理解,这里也简单给大家介绍一下。这里介绍的版本是RxJava 1.X版本的, 而在去年的早些时候,官方便宣布,将在一段时间后不再对 RxJava 1.x 进行维护,推出了RxJava2.X版本,既然有新的,为什么不介绍新的呢?因为目前最新的Hystrix版本1.5.12中使用的RxJava是1.2版本的,而2.X版本的api改动还是比较大的,所以为了大家能更加简单的理解Hystrix,所以这里是对1.X版本的介绍。 响应式编程是什么 响应式编程是一种基于异步数据流概念的编程模式,有点类似于JAVA里面的lambda表达式,相信大家都很熟悉lambda吧。数据流,stream,大家肯定不陌生,我们可以对stream有很多操作,filter、map、reduce 等常见操作。然后响应式中的核心就是响应二字,响应什么呢?响应的是事件,event 。 而流就是一个按照时间进行排序的事件序列。RxJava里面的事件是基于观察者模式,事件流将从上往下,从订阅源传递到观察者。 RxJava中重要概念 RxJava 有四个基本概念:Observable (可观察者,即被观察者)、 Observer (观察者)、 Subscriber (订阅,是Observer的抽象实现类,本质上使用是一样的)、事件。Observable 和 Observer 通过 subscribe() 方法实现订阅关系,从而 Observable 可以在需要的时候发出事件来通知 Observer。Observable 就像是一个生产者,在不断的生产消息,而Subscriber 和 Observer 就像是一个消费者,在不断的消费消息 另外, RxJava 的事件回调方法还定义了两个特殊的事件,在Hystrix中用得也非常多:onCompleted() 和 onError()。 onCompleted(): 事件队列完结。RxJava 不仅把每个事件单独处理,还会把它们看做一个队列。RxJava 规定,当不会再有新的 onNext() 发出时,需要触发 onCompleted() 方法作为标志。onError(): 事件队列异常。在事件处理过程中出异常时,onError() 会被触发,同时队列自动终止,不允许再有事件发出。 怎么做 说了这么多概念,估计大家都是一头雾水,我们直接来些实际的,加深大家的印象理解。用多的自然而然就会了,就懂了,这里说得可能不是最全的,但是说的都是Hystrix中用得很多的一些操作符,加深大家对Hystrix的理解,看源码就会容易一些。 例子 Observable<String> producer = Observable.create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { subscriber.onNext("apple"); subscriber.onNext("orange"); subscriber.onCompleted(); } }); Subscriber<String> consumer = new Subscriber<String>() { @Override public void onNext(String s) { LOG.

【Redis】获取没有设置ttl的key脚本

一 前言 在运维Redis的时候,总会遇到使用不规范的业务设计,比如没有对key设置ttl,进而导致内存空间吃紧,通常的解决方法是在slave上dump 出来所有的key ,然后对文件进行遍历再分析。遇到几十G的Redis实例,dump + 分析 会是一个比较耗时的操作,为此,我开发了一个小脚本直接连接Redis 进行scan 遍历所有的key,然后在检查key的ttl,将没有ttl的key输出到指定的文件里面。 二 代码实现 # encoding: utf-8 """ author: yangyi@youzan.com time: 2018/4/26 下午4:34 func: 获取数据库中没有设置ttl的 key """ import redis import argparse import time import sys class ShowProcess: """ 显示处理进度的类 调用该类相关函数即可实现处理进度的显示 """ i = 0 # 当前的处理进度 max_steps = 0 # 总共需要处理的次数 max_arrow = 50 # 进度条的长度 # 初始化函数,需要知道总共的处理次数 def __init__(self, max_steps): self.max_steps = max_steps self.i = 0 # 显示函数,根据当前的处理进度i显示进度 # 效果为[>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]100.00%

小程序之图片懒加载[完美方案,你不来看看?]

效果图 既然来了,把妹子都给你。 定义 懒加载,前端人都知道的一种性能优化方式,简单的来说,只有当图片出现在浏览器的可视区域内时,才设置图片正真的路径,让图片显示出来。这就是图片懒加载。 实现原理 监听页面的scroll事件,判读元素距离页面的top值是否是小于等于页面的可视高度 判断逻辑代码如下 element.getBoundingClientRect().top <= document.documentElement.clientHeight ? 显示 : 默认 我们知道小程序页面的脚本逻辑是在JsCore中运行,JsCore是一个没有窗口对象的环境,所以不能在脚本中使用window,也无法在脚本中操作组件。 所以关于图片懒加载就需要在数据上面做文章了。 页面 页面上面只需要根据数据的某一个字段来判断是否显示图片就可以了,字段为Boolean类型,当为false的时候显示默认图片就行了。 代码大概长成这样 <view wx:for="{{list}}" class='item item-{{index}}' wx:key="{{index}}"> <image class="{{item.show ? 'active': ''}}" src="{{item.show ? item.src : item.def}}"></image> </view> 复制代码 布局跟简单,view组件里面有个图片,并循环list,有多少就展示多少 image组件的src字段通过每一项的show来进行绑定,active是加了个透明的过渡 样式 image{ transition: all .3s ease; opacity: 0; } .active{ opacity: 1; } 复制代码 逻辑 本位主要讲解懒加载,所以把数据写死在页面上了 数据结构如下: 我们使用两种方式来实现懒加载,准备好没有,一起来快乐的撸码吧。 WXML节点信息 小程序支持调用createSelectQuery创建一个SelectorQuery实例,并使用select方法来选择节点,并通过boundingClientRect来获取节点信息。 wx.createSelectorQuery().select('.item').boundingClientRect((ret)=>{ console.log(ret) }).exec() 复制代码 显示结果如下 悄悄告诉你,小程序里面有个 onPageScroll函数,是用来监听页面的滚动的。 还有个 getSystemInfo函数,可以获取获取系统信息,里面包含屏幕的高度。 接下来,思路就透彻了吧。还是上面的逻辑, 扒拉扒拉直接写代码就行了,这里只写下主要的逻辑,完整代码请戳文末github

局域网打印机共享时好时坏问题

问题:局域网打印机pc01上 系统为win8.1 本地安装好用,当打印服务器,pc02 和pc03 共享连接pc01打印进,安转搞好时能打印时而不能打印?自己苦思研究查阅资料,看到一个海纳百川的总结,处理后目前正常使用。分享给大家 检查下面条件是否满足: 1、guest用户的开启 2、同一个工作组 3、安装“NWLink ipX/SPX/NetBIOS Compatible Transport PRotocol”协议 4、组策略删除“拒绝从网络访问这台计算机”项中的Guest账户即 5、确保打印服务器的“本地连接”属性中勾选了“Microsoft 网络的文件和打印机共享”项。 6、Internet连接防火墙 注意事项 设置打印机共享要注意到几项: 1、guest用户的开启,因为在有些安全设置里面guest用户是被禁止的!因此要保证guest用户总数有效。还有在guest设置的时候会有个选项要求下次登录更改密码,这个选项要去掉。这就是造成时好时坏的原因。 2、为了让打印机的共享能够顺畅,我们必须在主机和客户机上都安装“文件和打印机的共享协议”。 NETbios这个协议要看看是否安装好了,如果没有从要记得安装上。 3、现象一:网上邻居无法正常浏览 在Windows XP中共享打印机,首先要做的并不是直接在工作站中安装网络打印机,而是应该先看看“网上邻居”中的“查看工作组计算机”项是否能正常浏览、是否出现安装有打印机的计算机(下称打印服务器)。如果能够找到打印服务器,则表示共享打印机的基本条件已经具备,如果出现错误,则应首先解决这个问题。 解决办法:在确认局域网工作组名称一致的前提下,进入“本地连接”属性窗口,点击“安装”按钮添加“NWLink ipX/SPX/NetBIOS Compatible Transport PRotocol”协议,现在不用重启即可解决无法查看工作组计算机或是单击“查看工作组计算机”项后出现的“没有权限浏览某某工作组……”之类的问题。 现象二:无法浏览打印服务器 能正常浏览“网上邻居”后,首先要双击打印服务器图标,进入其中看共享的打印机是否存在,如存在,则表示当前工作站有权限对此打印机进行安装、打印之类的操作,如果看不到共享打印机或是无法浏览打印服务器,则表示当前工作站的权限不够。 解决办法:这个问题要从两方面来解决,一是在打印服务器中开放Guest账户,并在组策略中依次进入“计算机配置→Windows设置→安全设置→本地策略→用户权利指派”,删除“拒绝从网络访问这台计算机”项中的Guest账户即可;二是要确保打印服务器的“本地连接”属性中勾选了“Microsoft 网络的文件和打印机共享”项。 现象三:工作站搜索不到共享打印机 这是绝大多数局域网用户在Windows XP工作站中安装共享打印机时最容易遇见的问题,通常的表现形式是在共享打印机列表中只出现“Microsoft Windows Network”的信息,而共享打印机却搜索不到。 解决办法:这个问题有三个解决方法。一是在为“本地连接”安装“NWLink IPX/SPX/NetBIOS Compatible Transport Protocol”协议后,通常就可以搜索到共享打印机了;二是直接在“网上邻居”中双击进入打印服务器后,右键点击共享打印机图标,在弹出的快捷菜单中选择“连接”,在弹出的提示框中点击“是”按钮即可快速安装好共享打印机;三是检查打印服务器的“本地连接”是否启用了“Internet连接防火墙”功能,如果开启了,请取消该功能,如果既想使用“Internet连接防火墙”功能,又想共享文件和打印机,则要安装NetBEUI协议(非路由协议)。

C++ x的y次方对n取模

模运算满足分配率,对于任意的整数 a,b,q,r,n,可以构造: a = K1 * n + q b = K2 * n + r 则 (a*b) mod n = ((a mod n) * (b mod n)) mod n = q * r int pow(int x, int y, int mod) { int res = 1; while(y) { if(y & 1) { res = (res * x) % mod; } x = (x * x) % mod; y = y / 2; } return res; } 参考: https://www.

c#读取系统下所有执行文件窗体名称及句柄

获得窗体的句柄可以用GetWindow方法获得窗体标题用GetWindowText方法,显示隐藏某个窗体用ShowWindow方法,给你举个例子 using System.Runtime.InteropServices; private const int WS_VISIBLE =268435456;//窗体可见 private const int WS_MINIMIZEBOX= 131072;//有最小化按钮 private const int WS_MAXIMIZEBOX= 65536;//有最大化按钮 private const int WS_BORDER =8388608;//窗体有边框 private const int GWL_STYLE =(-16);//窗体样式 private const int GW_HWNDFIRST =0; private const int GW_HWNDNEXT =2; private const int SW_HIDE = 0; private const int SW_SHOW = 5; [DllImport("User32.dll")] private extern static intGetWindow(int hWnd, int wCmd); [DllImport("User32.dll")] private extern static intGetWindowLongA(int hWnd, int wIndx); [DllImport("user32.dll")] private static extern boolGetWindowText(int hWnd, StringBuilder title, int maxBufSize);

在 Matlab 中如何输入希腊字母等特殊字符

在 Matlab 中希望输入希腊字母等特殊字符用 \ 加拼音 如下表: α \alpha β \betaγ \gammaθ \thetaΘ \ThetaГ \Gammaδ \deltaΔ \Deltaξ \xi Ξ \Xiη \eltaε \epsilongζ \zetaμ \miuυ \nu τ \tau λ \lamda^ \Lamdaπ \pi∏ \Piσ \sigma∑ \Sigmaφ \phi Φ \Phiψ \psi Ψ \Psiχ \chiω \ommigaΩ \Ommiga左箭头 \leftarrow右箭头 \rightarrow上箭头 \uparrow 注: 可用 {} 把须放在一起的括起来 Matlab图形中允许用 TEX 文件格式来显示字符。使用\bf,\it,\rm表示黑体,斜体,正体字符,特别注意大括号{ }的用法。 更多参见Matlab中下标,斜体,及希腊字母的使用方法

递归、回溯和DFS的区别

递归是一种算法结构,回溯是一种算法思想。一个递归就是在函数中调用函数本身来解决问题。回溯就是通过不同的尝试来生成问题的解,有点类似于穷举,但是和穷举不同的是回溯会“剪枝”。 剪枝的意思也就是说对已经知道错误的结果没必要再枚举接下来的答案了,比如一个有序数列1,2,3,4,5,我要找和为5的所有集合,从前往后搜索我选了1,然后2,然后选3的时候发现和已经大于预期,那么4,5肯定也不行,这就是一种对搜索过程的优化。 回溯搜索是深度优先搜索(DFS)的一种。对于某一个搜索树来说(搜索树是起记录路径和状态判断的作用),回溯和DFS,其主要的区别是,回溯法在求解过程中不保留完整的树结构,而深度优先搜索则记下完整的搜索树。 为了减少存储空间,在深度优先搜索中,用标志的方法记录访问过的状态,这种处理方法使得深度优先搜索法与回溯法没什么区别了。 递归的一般结构: void f() { if(符合边界条件) { /////// return; } //某种形式的调用 f(); } 回溯的一般结构: void DFS(int 当前状态) { if(当前状态为边界状态) { 记录或输出 return; } for(i=0;i<n;i++) //横向遍历解答树所有子节点 { //扩展出一个子状态。 修改了全局变量 if(子状态满足约束条件) { dfs(子状态) } 恢复全局变量//回溯部分 } } BFS和DFS相似。BFS显式用队列,DFS隐式用栈,即递归。 当然,对于DFS,用递归可能会造成栈溢出,所以也可以更改为显示栈。 以下以走迷宫问题为力,做一下说明: *表示可走 #表示障碍 T表示出口 入口是(1,1),数据保证左上角是入口。 #include<iostream> using namespace std; char maze[100][100]; bool flag[100][100]; int dx[]={0,0,1,-1}; int dy[]={1,-1,0,0}; int m,n; bool dfs(int x,int y) { flag[x][y]=1; //走过的路标记为1 if(maze[x][y]=='T')return true; for(int i=0;i<4;i++) //四个方向 { int nx=x+dx[i]; int ny=y+dy[i]; if(flag[nx][ny]==0||maze[nx][ny]=='*'||maze[nx][ny]=='T'&&nx>0&&ny>0&&nx<m+1&&ny<n+1) { return dfs(nx,ny); flag[nx][ny]=0; //回溯,将标记重新标记为0 } } return false; //找不到返回false } int main() { while(cin>>m>>n){ memset(maze,0,sizeof(maze)); memset(flag,0,sizeof(flag)); for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) cin>>maze[i][j]; if(dfs(1,1))cout<<"

Koa2 源码学习(上)

引言 最近读了一下Koa2的源码;在阅读Koa2 (2.3.0) 的源码的过程中,我的感受是整个代码设计精巧,思路清晰,是一个小而精的 nodejs web服务框架。 设计理念 作为web服务框架,都是要围绕核心服务而展开的。那什么是核心服务呢?其实就是接收客户端的一个http的请求,对于这个请求,除了接收以外,还有解析这个请求。所以说会有 HPPT:接收 -> 解析 -> 响应 在响应客户端的时候,也有很多种方式,比如返回一个html页面,或者json文本。在解析请求和响应请求的中间,会有一些第三方的中间件,比如 日志、表单解析等等来增强 koa 的服务能力,所以 koa 至少要提供 "请求解析"、"响应数据"、"中间件处理" 这三种核心能力的封装,同时还需要有一个串联他们执行环境的上下文(context) HTTP接收解析响应中间件执行上下文 上下文可以理解为是http的请求周期内的作用域环境来托管请求响应和中间件,方便他们之间互相访问。 以上分析是站在单个http请求的角度来看一个web服务能力。那么站在整个网站,站在整个后端服务的角度来看的话,能够提供 "请求"、"响应"、"解析"、"中间件"、"http流程全链路" 这些服务能力的综合体,可以看做是一个应用服务对象。如果把这些全放到 koa 里的话,那么对应的就是: ApplicationContextRequestResponseMiddlewaresSessionCookie Koa的组成结构 首先看下koa的目录结构 application.js:框架入口;负责管理中间件,以及处理请求context.js:context对象的原型,代理request与response对象上的方法和属性request.js:request对象的原型,提供请求相关的方法和属性response.js:response对象的原型,提供响应相关的方法和属性 // application.js const isGeneratorFunction = require('is-generator-function'); // 判断当前传入的function是否是标准的generator function const debug = require('debug')('koa:application'); // js调试工具 const onFinished = require('on-finished'); // 事件监听,当http请求关闭,完成或者出错的时候调用注册好的回调 const response = require('./response'); // 响应请求 const compose = require('koa-compose'); // 中间件的函数数组 const isJSON = require('koa-is-json'); // 判断是否为json数据 const context = require('.

系统架构原理分析(4)——负载均衡

1. 什么是负载均衡 1.1 负载均衡的定义 负载均衡是由多台服务器以对称的方式组成一个服务器集合,每台服务器都具有等价的地位,都可以单独对外提供服务而无须其他服务器的辅助。通过某种负载分担技术,将外部发送来的请求均匀分配到对称结构中的某一台服务器上,而接收到请求的服务器独立地回应客户的请求。均衡负载能够平均分配客户请求到服务器列阵,籍此提供快速获取重要数据,解决大量并发访问服务问题。这种群集技术可以用最少的投资获得接近于大型主机的性能。这种技术可以运用在流量拥塞时、访问路径过长、网民数量大增、运行这种系统负载、大大的提高了系统的可靠性、负载均衡技术解决网络拥塞的问题、处理大量并发的访问服务能力、提高服务器的响应速度、为用户提供更好的访问质量。所以说负载均衡是智能化、高性能、灵活性的技术。 但是要如何将不同的用户的流量分发到不同的服务器上面呢? 早期的方法是使用DNS做负载,通过给客户端解析不同的IP地址,让客户端的流量直接到达各个服务器。但是这种方法有一个很大的缺点就是延时性问题,在做出调度策略改变以后,由于DNS各级节点的缓存并不会及时的在客户端生效,而且DNS负载的调度策略比较简单,无法满足业务需求,因此就出现了负载均衡。如下图所示: 客户端的流量首先会到达负载均衡服务器,由负载均衡服务器通过一定的调度算法将流量分发到不同的应用服务器上面,同时负载均衡服务器也会对应用服务器做周期性的健康检查,当发现故障节点时便动态的将节点从应用服务器集群中剔除,以此来保证应用的高可用。 1.2 负载均衡的分类 负载均衡又分为四层负载均衡和七层负载均衡。 (1)四层负载均衡工作在OSI模型的传输层,主要工作是转发,它在接收到客户端的流量以后通过修改数据包的地址信息将流量转发到应用服务器。 (2)七层负载均衡工作在OSI模型的应用层,因为它需要解析应用层流量,所以七层负载均衡在接到客户端的流量以后,还需要一个完整的TCP/IP协议栈。七层负载均衡会与客户端建立一条完整的连接并将应用层的请求流量解析出来,再按照调度算法选择一个应用服务器,并与应用服务器建立另外一条连接将请求发送过去,因此七层负载均衡的主要工作就是代理。 2. 四层和七层负载均衡的区别? 2.1 技术原理区别 所谓四层负载均衡,也就是主要通过报文中的目标地址和端口,再加上负载均衡设备设置的服务器选择方式,决定最终选择的内部服务器。 以常见的TCP为例,负载均衡设备在接收到第一个来自客户端的SYN 请求时,即通过上述方式选择一个最佳的服务器,并对报文中目标IP地址进行修改(改为后端服务器IP),直接转发给该服务器。TCP的连接建立,即三次握手是客户端和服务器直接建立的,负载均衡设备只是起到一个类似路由器的转发动作。在某些部署情况下,为保证服务器回包可以正确返回给负载均衡设备,在转发报文的同时可能还会对报文原来的源地址进行修改。 所谓七层负载均衡,也称为“内容交换”,也就是主要通过报文中的真正有意义的应用层内容,再加上负载均衡设备设置的服务器选择方式,决定最终选择的内部服务器。 以常见的TCP为例,负载均衡设备如果要根据真正的应用层内容再选择服务器,只能先代理最终的服务器和客户端建立连接(三次握手)后,才可能接受到客户端发送的真正应用层内容的报文,然后再根据该报文中的特定字段,再加上负载均衡设备设置的服务器选择方式,决定最终选择的内部服务器。 负载均衡设备在这种情况下,更类似于一个代理服务器。负载均衡和前端的客户端以及后端的服务器会分别建立TCP连接。所以从这个技术原理上来看,七层负载均衡明显的对负载均衡设备的要求更高,处理七层的能力也必然会低于四层模式的部署方式。那么,为什么还需要七层负载均衡呢? 2.2 应用场景的需求 七层应用负载的好处,是使得整个网络更”智能化”。例如访问一个网站的用户流量,可以通过七层的方式,将对图片类的请求转发到特定的图片服务器并可以使用缓存技术;将对文字类的请求可以转发到特定的文字服务器并可以使用压缩技术。 当然这只是七层应用的一个小案例,从技术原理上,这种方式可以对客户端的请求和服务器的响应进行任意意义上的修改,极大的提升了应用系统在网络层的灵活性。很多在后台,(例如Nginx或者Apache)上部署的功能可以前移到负载均衡设备上,例如客户请求中的Header重写,服务器响应中的关键字过滤或者内容插入等功能。 另外一个常常被提到功能就是安全性。网络中最常见的SYN Flood攻击,即黑客控制众多源客户端,使用虚假IP地址对同一目标发送SYN攻击,通常这种攻击会大量发送SYN报文,耗尽服务器上的相关资源,以达到Denial of Service(DoS)的目的。 从技术原理上也可以看出,四层模式下这些SYN攻击都会被转发到后端的服务器上;而七层模式下这些SYN攻击自然在负载均衡设备上就截止,不会影响后台服务器的正常运营。另外负载均衡设备可以在七层层面设定多种策略,过滤特定报文,例如SQL Injection等应用层面的特定攻击手段,从应用层面进一步提高系统整体安全。 现在的7层负载均衡,主要还是着重于应用广泛的HTTP协议,所以其应用范围主要是众多的网站或者内部信息平台等基于B/S开发的系统。 4层负载均衡则对应其他TCP应用,例如基于C/S开发的ERP等系统。 2.3 七层应用需要考虑的问题 是否真的必要,七层应用的确可以提高流量智能化,同时必不可免的带来设备配置复杂,负载均衡压力增高以及故障排查上的复杂性等问题。在设计系统时需要考虑四层七层同时应用的混杂情况。 是否真的可以提高安全性。例如SYN Flood攻击,七层模式的确将这些流量从服务器屏蔽,但负载均衡设备本身要有强大的抗DDoS能力,否则即使服务器正常而作为中枢调度的负载均衡设备故障也会导致整个应用的崩溃。 是否有足够的灵活度。七层应用的优势是可以让整个应用的流量智能化,但是负载均衡设备需要提供完善的七层功能,满足客户根据不同情况的基于应用的调度。最简单的一个考核就是能否取代后台Nginx或者Apache等服务器上的调度功能。能够提供一个七层应用开发接口的负载均衡设备,可以让客户根据需求任意设定功能,才真正有可能提供强大的灵活性和智能性。 3. 负载均衡的算法 3.1. 随机算法 Random随机,按权重设置随机概率。在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。 3.2. 轮询及加权轮询 轮询(Round Robbin)当服务器群中各服务器的处理能力相同时,且每笔业务处理量差异不大时,最适合使用这种算法。 轮循,按公约后的权重设置轮循比率。存在慢的提供者累积请求问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。 加权轮询(Weighted Round Robbin)为轮询中的每台服务器附加一定权重的算法。比如服务器1权重1,服务器2权重2,服务器3权重3,则顺序为1-2-2-3-3-3-1-2-2-3-3-3- …… 3.3. 最小连接及加权最小连接 最少连接(Least Connections)在多个服务器中,与处理连接数(会话数)最少的服务器进行通信的算法。即使在每台服务器处理能力各不相同,每笔业务处理量也不相同的情况下,也能够在一定程度上降低服务器的负载。 加权最少连接(Weighted Least Connection)为最少连接算法中的每台服务器附加权重的算法,该算法事先为每台服务器分配处理连接的数量,并将客户端请求转至连接数最少的服务器上。 3.4. 哈希算法 普通哈希 一致性哈希一致性Hash,相同参数的请求总是发到同一提供者。当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。 3.5. IP地址散列 通过管理发送方IP和目的地IP地址的散列,将来自同一发送方的分组(或发送至同一目的地的分组)统一转发到相同服务器的算法。当客户端有一系列业务需要处理而必须和一个服务器反复通信时,该算法能够以流(会话)为单位,保证来自相同客户端的通信能够一直在同一服务器中进行处理。

实例属性和类属性,类绑定方法

实例属性和类属性 class Student(object): name = "Student" #类属性 def __init__(self, name): self.name = name #实例属性 添加类属性有两种方法,一种是 __init__中的self直接添加,或者通过实例绑定 s = Student() s.score = 99 当实例属性和类属性冲突的时候,实例属性会屏蔽掉类属性.下面的例子很好的说明了它: class Student(object): name = 'Student' s = Student() print(s.name) #Student s.name = 'Micheal' #给实例绑定name属性 print(s.name) #Micheal 实例属性屏蔽掉了类属性 print(Student.name) #Student 但类属性仍然存在 del s.name #会删除实例的name属性 print(s.name) #Student 一般都是给一个实例绑定一个属性,但若是绑定方法,可按以下方法设置: from types import MethodType class Student(object): pass def set_age(self, age): self.age = age s = Student() s.set_age = MethodType(set_age, s) #s.

java.math.BigDecimal类multiply的使用

java.math.BigInteger.multiply(BigInteger val) 返回一个BigInteger,其值是 (this * val). 声明 以下是java.math.BigInteger.multiply()方法的声明 public BigInteger multiply(BigInteger val) 参数 val - 通过此BigInteger乘以的值 返回值 该方法返回一个BigInteger对象的值是 this * val. 异常 NA 例子 下面的例子显示math.BigInteger.multiply()方法的用法 package com.yiibai; import java.math.*; public class BigIntegerDemo { public static void main(String[] args) { // create 3 BigInteger objects BigInteger bi1, bi2, bi3; bi1 = new BigInteger("7"); bi2 = new BigInteger("20"); // multiply bi1 with bi2 and assign result to bi3 bi3 = bi1.multiply(bi2); String str = bi1 + "

Android 代码质量管理

前言 “任何一个傻瓜都能写出计算机可以理解的代码,唯有写出人类容易理解的代码,才是优秀的程序员。” 代码不仅仅是人类和计算机沟通的语言,它也是建立在程序员之间的桥梁,两个程序员在沟通的时候,任何富有表达力的言语都不如直接阅读对方一段代码。 代码也是公司的一笔特殊财富,因为它不可能永远被同一个程序员维护,如果代码的可读性很差的话,很可能导致这笔财富无法传承下来,前功尽弃。 具有良好可读性的代码能让功能的扩展和BUG的修复更顺利,增加新功能、修改某个BUG都需要你首先理解代码。 所以,提高代码质量是很有必要的,本文将介绍个人在实践中认为能够提高代码质量的方法,希望对大家有所帮助。 理想和现实 软件缺陷 世上本没有BUG 随着功能的增加,便有了BUG 老的BUG改了,可能引入新的BUG 事实: 我们的软件,在发布前,其实就已经百病缠身了。 烂代码的伤害 1. 不利于其他同事维护和更新2. 维护、时间成本的增加3. 无法传承下去,维护成本比重新开发成本更高。 软件发布后的情形: 0、领导:这次发布的版本BUG太多了,客户天天往我手机打电话,你们在搞什么东西? 1、项目经理:加班、加班、加班,都留下来给我加班 (把地给我扫干净!) 2、程序员:丧失工作热情 (我们一个个都是怀揣着梦想进入公司的,结果待了2年,发现并不是这么美好。 我常听到程序员说:哎,我们的代码就是一坨X。X是一种什么样的状态,你们懂的。 都说写代码是艺术,有人说,我怎么感觉像蓝领,没啥技术含量呢?) 3、结果:频繁跳槽 (其实是被动跳槽,代码不敢维护下去了,随便一个小改动都会引来新的问题……于是从一个火坑跳进了另一个更大的火坑。) 发现、修改和预防烂代码 疑问1:我们如何发现烂代码? 多看网上的大神写的代码,看多了自然就有识别的能力了。 疑问2:烂代码要不要改呢?应该怎么改? 但愿客户不要发现……不影响功能,反正用户也看不到,不要改了时间来不及了,我们下个版本再说吧 疑问3:如果烂代码不是先天性的,那是不是可以预防? 没有好的方式去预防。 制约程序员编写高质量代码的因素 1. 对需求和设计的理解不透彻 2. 对软件业务流程不熟悉 3. 没有开发经验,不知道怎样的代码是好的 4. 对开发工具或开发语言不熟悉 5. 缺少监督体系或不重视质量评估 6. 受情绪因素的影响等因素 7. 其它非代码因素也起着关键作用 - 对于一些经验丰富的编程人员,他们是知道怎么写代码是最好的,最有效率的,但是为什么他们写出的代码也很烂呢?—— 破窗效应 好代码的特性 可读性可维护性 可变更性 正确性 可读性 重视开发规范 1. 代码整洁、类、变量、方法命名规则2. 代码样式,缩进与换行3. 多写注释 可维护性 方法清晰,容易理解函数不要超过100行 类不要超过1000行不要硬编码 定义常量或配置文件修改常用属性 保持代码简洁 函数越短小越好 可变更性 代码复用,减少冗余。适当的利用23种设计模式 多人开发可以采用MVP或者其他开发模式。 设计原则 ① 单一职责,一个类或者一个方法只做一样事情。

面试题(一)——互联网公司面试题整理

百度移动游戏 1.ArrayList和LinkedList区别 2.HashMap实现原理,内部构造,JDK1.8的实现 3.如何设计数据库 4.JVM堆为什么分成年轻代和老年代 5.ConcurrentHashMap原理 6.一个方法中定义一个int型变量和一个Integer变量,这两个变量什么时候会被回收 阿里高德 1.LinkedList是单向链表还是双向链表 2.JVM内存模型 3.GC算法以及回收器(CMS) 4.TCP、UDP、IP、HTTP分别处于哪层 阿里 1.JVM内存模型 2.ZooKeeper选举 爱奇艺 1.CPU100%如何找问题 2.MySQL两种存储引擎(Innodb和MyISAM)的区别 3.Redis和Memecache区别 微博 1.Redis存储一个k-v占多少内存 2.MySQL索引问题,聚簇索引(a,b,c),查询时使用条件b和c是否走索引 3.如何高效的将字符串IP翻译成整数 360面试 1.如何实现一个list,set 2,list如何去重 3.如何实现线程在同一时刻执行 4.线程的实现方式 5.项目的演示 6.hashmap,hashtable的区别 蓝汛 1.redis 2.netty 3. 题目讲解 1.Java类加载器机制 类加载器结构: 引导类加载器(BootstrapClassLoader,原生代码写的,不继承自ClassLoader):加载Java核心库 |/ 扩展类加载器(ExtClassLoader,继承自ClassLoader,parent==null):加载Java的扩展库 |/ 系统类加载器(SystemClassLoader,继承自ClassLoader,parent==ExtClassLoader):根据 Java 应用的类路径(CLASSPATH)来加载Java类,可以通过 ClassLoader.getSystemClassLoader()来获取它。 类加载过程: 加载类时采用代理机制,当前类加载器首先会让父类加载器进行加载,如果加载不到,在自己加载。web类加载器机制不同,优先自己加载(除Java核心类库外)。 如何开发自己的类加载器: 继承自ClassLoader,重写findClass(),方法内获取到字节码后调用父类的defineClass()即可。不可重写loadClass()(LoadClass内部实现代理机制逻辑) 虚拟机的类加载机制:虚拟机把描述类的数据class文件加载到内存,并对数据进行校验,转换解析和初始化,最终形成可被虚拟机直接使用的java类 在类装载到一个jvm中需要经过 加载——>链接->初始化 (a)校验:检查载入Class文件数据的正确性; (b)准备:给类的静态变量分配存储空间; (c)解析:将符号引用转成直接引用; 2.垃圾回收算法 a.引用计数法 通过对一个对象增加一个计数器方式实现。 优点:实现简单 缺点:无法解决循环引用问题 b.标记-清除算法 通过根节点,标记所有从根节点可达的对象,然后将未被标记的对象进行清除。、 优点:可解决循环引用问题 缺点:造成内存碎片 c.复制算法 将原有内存划分成两块,每次只使用一块,回收时将正在使用的内存中存活的对象复制到另一块内存中,然后清除之前内存中剩余的对象,互换两块内存的角色。 优点:如果存活对象很少,那么需要复制的对象将很少,效率很高,同时内存也会连续 缺点:将内存折半 d.标记-压缩算法 使用标记方式寻找存活对象,然后将存活对象压缩到内存的一端,清理到外界的内存即可。 优点:内存连续 缺点:需要移动对象,所以需要改变很多引用地址 e.

python编程从入门到实践练习12-5

#main.py import pygame import sys from ship import Ship import game_functions as gf from settings import Settings from pygame.sprite import Group def run_game(): """飞机位于屏幕左边""" pygame.init() ai_settings = Settings() screen = pygame.display.set_mode((ai_settings.screen_width, ai_settings.screen_height)) ship = Ship(screen) bullets = Group() pygame.display.set_caption("Alien Invasion") while True: gf.check_events(ship, ai_settings, bullets, screen) ship.update(ship) bullets.update() for bullet in bullets.copy(): if bullet.rect.left > ai_settings.screen_width: bullets.remove(bullet) #print(len(bullets)) gf.update_screen(screen, ai_settings, ship, bullets) run_game() #ship.py """为方便起见,将子弹类和飞船类都写在这里""" import pygame from pygame.sprite import Sprite class Ship(): "

项目总结(关于fixed/absolute固定的底部按钮被input输入框的键盘顶上去的问题一般安卓手机会出现这种问题)

解决方法:监控屏幕大小的变化,当屏幕变小的时候让按钮隐藏起来,当屏幕大小与当前屏幕保持一致的时候,让按钮正常显示。 原生js解决方法: var h = document.body.scrollHeight; window.onresize = function(){ if (document.body.scrollHeight < h) { document.getElementsByTagName("nav")[0].style.display = "none"; }else{ document.getElementsByTagName("nav")[0].style.display = "block"; } }; 加黑倾斜的是重点,记住 另外的jquery的写法 var h=$(window).height(); $(window).resize(function() { if($(window).height()<h){ $('.footer').hide(); }else{ $('.footer').show(); } } // 这是在项目中遇到的情况 另外一种情况出现在了苹果手机上,底部的input的框会被下面弹起的键盘遮住 具体情况看这个链接:https://www.cnblogs.com/wangjae/p/7095619.html 解决方法: $("input").on("click", function() { setTimeout(function(){ document.body.scrollTop = document.body.scrollHeight; },300); }) scrollTop和scrollHeight的含义和用法,百度上多的很。不过确实提供了一种思路。

SX1278与STM8L的精美结合。

转发请注重原创出处,谢谢! 一. 引言 能耗对于电池供电的产品来说是一个重大的问题,一旦电能耗尽设备将“罢工”,在某些场合电能意味着电子产品的生命。物联网时代将会有越来越多电池供电的设备通过无线通信连接,降低能耗再次摆在工程师的桌面上—解决它。不但具备空旷环境传输5km的超长距离优势,还将休眠能耗降低到极致(0.4uA,带RTC为1.4uA)。我们是怎么做到的呢?接下来,一步一步解密。 二. 硬件设计 1. 选用低功耗器件 终端MCU选用STM8L151C8T6,它属于超低功耗,不带RTC休眠为400nA,带RTC下休眠为1.4uA。该MCU拥有较大的RAM(4KB)和自带EEPROM(2KB),不用扩展外部存储设备,进行一步降低功耗和成本。 终端射频芯片选用SX1278,在休眠模式下,该芯片功耗低至忽略不计。 2. 尽可能快地让射频模块休眠 SX1278属于LoRa TM扩频调制技术,它的远距离优势得益于调制增益,不是靠增大发射功率(那将消耗更多电能)。该射频芯片的电流消耗如下:休眠<0.2uA,空闲=1.6mA,接收=12mA,发射(最大功率)=120mA. 终端MCU通过“中断+定时器超时”方式控制SX1278,一旦射频完成发送或接收,立即进入休眠模式。 第一: 虽然MCU是停机了,但是电路板还有其他的芯片在工作,它们仍然在消耗电量,所以我们在停机前应该要把其他芯片给关闭(可以通过特定的指令或者片选线)。条件好的可以直接用切断它们的电源。 第二: 我是这样理解的:进入停机模式后,只是MCU中最耗电的内核部分被关了,而所有寄存器和内存中的值是保持不变的,所以它的外设还在消耗电量,所以我们要在停机之前把开启的外设给关了。这里要注意一点:外设开启时是先开时钟再设置寄存器,关闭时先清除寄存器再关闭时钟。我是这样理解的:操纵一个外设的寄存器肯定是需要时钟的,如果我们先把时钟给关了,那么还怎么操作寄存器呢,如果光关了时钟,不清寄存器的相应位,那么外设还处于“静态耗电”的状态。在研究低功耗的过程中,我被这个坑了好久。关于这一点的实例可以参考这篇博客: http://blog.csdn.net/qq_25186745/article/details/52777375 第三: 关于IO口的电平,这个是非常重要的一点,和之前提到的外设一样,GPIO也是一种外设,但是特殊的是,这个外设是和芯片外部直接打交道的,如果GPIO外部接了个上拉电阻,而你在停机之前设置的IO口是低电平的,那么电流不就通过电阻,流到IO口里来了,比如正常的说接了个10k的上拉电阻,接到3.3v电压上,那么电流就是330uA,这个值可不小呢,stm8l在停机时极限最小电流好像能达到0.4uA。那么你这个电路就是因为这个电阻,停机电流比别人大了将近800倍了,那么假如你的产品能待机1年,人家待机800年,这还怎么比?所以IO口是绝对不能被忽视的。stm8l芯片复位以后所有引脚都是浮空输入模式,理论上悬浮空输入时IO口的状态为高阻态是最省电的,那么我们只要把所有IO都DeInit就可以了。但是事实上不是,我把没有用到的管脚全部推挽输出高电平或低电平,不用的外部晶振的引脚要改为上拉输入才省电,外部有上拉下拉电阻的引脚分别推挽输出高电平和低电平,一般电路中上拉电阻比较多(比如IIC的总线外部都有上拉的)。和外部芯片相连的引脚都推挽输出低电平,因为外部芯片断电后所有引脚都是高阻态或接地的吧,如果你弄个高电平,就可能会有电流流过去。 但是。。但是。。。。但是。。。。。。不是所有STM8L系列的芯片GPIO都是一样的。 比如 / 所有端口输出开漏,低电平 GPIO_Init(GPIOA, GPIO_Pin_All, GPIO_Mode_Out_OD_Low_Slow); GPIO_Init(GPIOB, GPIO_Pin_All, GPIO_Mode_Out_OD_Low_Slow); GPIO_Init(GPIOC, GPIO_Pin_All, GPIO_Mode_Out_OD_Low_Slow); GPIO_Init(GPIOD, GPIO_Pin_All, GPIO_Mode_Out_OD_Low_Slow); GPIO_Init(GPIOE, GPIO_Pin_All, GPIO_Mode_Out_OD_Low_Slow); GPIO_Init(GPIOF, GPIO_Pin_All, GPIO_Mode_Out_OD_Low_Slow); GPIO_Init(GPIOG, GPIO_Pin_All, GPIO_Mode_Out_OD_Low_Slow); 或者 / 所有端口输出开漏,高电平 GPIO_Init(GPIOA, GPIO_Pin_All, GPIO_Mode_Out_OD_Hig_Slow); GPIO_Init(GPIOB, GPIO_Pin_All, GPIO_Mode_Out_OD_Hig_Slow); GPIO_Init(GPIOC, GPIO_Pin_All, GPIO_Mode_Out_OD_Hig_Slow); GPIO_Init(GPIOD, GPIO_Pin_All, GPIO_Mode_Out_OD_Hig_Slow); GPIO_Init(GPIOE, GPIO_Pin_All, GPIO_Mode_Out_OD_Hig_Slow); GPIO_Init(GPIOF, GPIO_Pin_All, GPIO_Mode_Out_OD_Hig_Slow); GPIO_Init(GPIOG, GPIO_Pin_All, GPIO_Mode_Out_OD_Hig_Slow);

Dijkstra算法求无向带权图最短路径——Java

Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。 Dijkstra算法采用的是贪心算法的策略,在整个算法过程中一直要维护两个表,这两个表分别表示尚未遍历的结点和已遍历的结点。大概过程如下: 声明两个集合,open和close,open用于存储未遍历的节点,close用来存储已遍历的节点;初始阶段,将初始节点放入close,其他所有节点放入open;以初始节点为中心向外一层层遍历,获取离指定节点最近的子节点放入close并从新计算路径,直至close包含所有子节点。 我在Intellij IDEA中实现了此算法,与BFS算法一样,首先我们需要构建一个图进行测试。在这里,我构建如下图: 以下为构建代码,首先创建Node对象用于封装图中的vertex结点信息,它包括结点的名字和子结点,子结点就是与之相邻的所有结点。 public class Node { private String name; private Map<Node,Integer> child=new HashMap<>(); public Node(String name){ this.name=name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Map<Node, Integer> getChild() { return child; } public void setChild(Map<Node, Integer> child) { this.child = child; } } 其中自动生成了constructor、getter和setter方法,方便进行结点操作。 MapBuilder用于初始化数据源,返回图的起始节点。 public class MapBuilder { public Node build(Set<Node> open, Set<Node> close){ Node nodeA=new Node("

【Python】【numpy-汇总3】所有排序函数的示例代码

1.排序函数 排序函数 说明 np.sort( ndarray) 排序,返回副本 np.unique(ndarray) 返回ndarray中的元素,排除重复元素之后,并进行排序 np.intersect1d( ndarray1, ndarray2) np.union1d( ndarray1, ndarray2) np.setdiff1d( ndarray1, ndarray2) np.setxor1d( ndarray1, ndarray2) 返回二者的交集并排序。 返回二者的并集并排序。 返回二者的差。 返回二者的对称差 2.函数的使用示例 np.sort 也可以参见官方manual:https://docs.scipy.org/doc/numpy/reference/generated/numpy.sort.html np.sort(a, axis=-1, kind='quicksort', order=None) # -*- coding: utf-8 -*- """ @author: tom Talk is cheap, show me the code Aim:numpy的排序函数示例 """ import numpy as np #排序,返回副本 #np.sort(ndarray, axis=-1, kind='quicksort', order=None) a = np.array([[1,9,2], [7,5,6], [4,8,3]]) #a中单独元素element所在axis都是0,如1,7,4和9,5,8,以及2,6,3都在axis=0上 #a中最内层的array所在axis都是1,如[1,9,2]和[7,5,6]以及[4,8,3]都在axis=1上 #说明:a是2维array,最大axis就是1,最小axis就是0 ret = np.sort(a) #sort along the last axis ''' [[1 2 9] [5 6 7] [3 4 8]] ''' ret = np.

python偏函数

python偏函数 今天白天看了一天的六级相关课程,只有晚上有时间,但晚上又划了半天水,学的并不多,学了python的偏函数.这个偏函数并非数学中的偏函数,而是指寻求方便,对某些函数值进行绑定.廖大神举得例子是int函数 int('123456')#返回的是将字符串变为整数的值,默认为十进值 int('123456',base=2)#通过关键字base可以将进制设置为二进制,但是这题我理解失误,以为是将123456变为二进制,但是其实错了,这是将123456视作二进制,将其转换为十进值,于是报错 ValueError: invalid literal for int() with base 2: '123456' int('123456',2)#省略base也行,不过此句任然报错 可以通过一个方法,将其默认视为2进制. #法1 def int2(x,base=2):#默认参数设置为2 return int(x,base) int2('10101010') #法2 import functools int2 = functools.partical(int, base=2) int2('1010101010') 法二即为偏函数 end:2018年04月22日00:27:54

《机器学习实战》第二章,KNN算法在jupyter中实验

1、首先在jupyter中New一个Untitle.ipynb,然后将它重命名为kNN.py,接着在kNN.py中输入一下代码(课本代码): 注:以下代码中,存在我自己的测试数据文件的路径,你们要改为自己测试数据文件的路径 from numpy import * import operator def createDataSet(): group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]]) labels = ['A','A','B','B'] return group, labels def classify0(inX, dataSet, labels, k): dataSetSize = dataSet.shape[0] diffMat = tile(inX, (dataSetSize, 1)) - dataSet sqdiffMat = diffMat**2 sqdistance = sqdiffMat.sum(axis=1) #print(sqdistance) distance = sqdistance**0.5 sortedDistIndex = distance.argsort() classCount = {} for i in range(k): voteIlabel = labels[sortedDistIndex[i]] classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1 sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True) return sortedClassCount[0][0] def file2matrix(filename): fr = open(filename) arrayOLines = fr.

《机器学习实战》第二章,之K-邻近算法-实验

一、准备:使用Python导入数据: 1、首先,创建名为kNN.py的Python模块,在kNN.py文件中添加下面代码: from numpy import * import operator def createDataSet(): group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]]) labels = ['A','A','B','B'] return group, labels 进入Python开发环境之后,输入下面命令: 二、实施kNN分类算法: 1、在kNN.py中再添加下面代码: def classify0(inX, dataSet, labels, k): dataSetSize = dataSet.shape[0] diffMat = tile(inX, (dataSetSize,1)) - dataSet sqDiffMat = diffMat**2 sqDistances = sqDiffMat.sum(axis=1) distances = sqDistances**0.5 sortedDistIndicies = distances.argsort() classCount={} for i in range(k): voteIlabel = labels[sortedDistIndicies[i]] classCount[voteIlabel] = classCount.get (voteIlabel,0) + 1 sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True) return sortedClassCount[0][0]

IDC机柜布线的日常操作规范

在整个网络布线工程中,机柜布线是一项非常讲究的工作。它和装衣服是完全不一样的,不能说按照个人的喜好去布线,它有自己的规则,如果装错了,就不能正常的完成工作了,严重的还会影响整个工程的质量。下面就和大家分享下IDC机柜布线的日常操作规范: 一.电源线插头与服务器电源接头两端要标签扎带 二.如果一个机柜有内外网的交换机,尽量用两种不同颜色网线区分开来 三.柜子与柜子之间走线要从机柜顶端方向布线 四.连接服务器与交换机两端的网线头后端要标记同编号的扎带标签,且与交换机端口号编号一致 五.电源线与网线分机柜两边走线,每一小节要用扎带扎好 六.机柜服务器不能太多台叠加一起,要用挡板分离开来,有助维护与服务器散热稳定性 七.交换机要用配套耳朵固定在机柜顶端,有助于网线的走位 八.贴好每台服务器ip或者根据应用划分的标签 九.贴好每台服务器的资产号,通过标签打印机把资产号+条形码一起打出来,以后核实到IDC机房核实资产,可以通过条形码扫描仪扫描出来。每台设备打印两张一致的,设备前面贴一个,设备边上贴一个,由于编号是唯一性的,预防资产号丢失 十.核心交换机接到二层交换机的网线两端或者光纤要用扎带标签贴好,写上此端口连接到哪个机柜号哪个交换机哪个端口号,如:con-to-6-3-C3560-7 十一.尽量不要在服务器贴ip地址,如:贴上应用标签,这样比较安全,一些托管商设备零散只能贴ip,交换机和防火墙不要贴上ip地址,写上内外网就行了,如:outside与inside 十二.查看机柜下面空调挡风口闸门是否打开,以免设备过热死机 十三.重装某台设备系统时,不要把显示器电源接在与服务器连接插排上面,每个机柜都有提供一个专门接显示器或者外接插排的插座,以免显示器电源接口因接触不好或者使用不当导致整个插排都断电。 十四.日常重整资源时,会不经意碰到网线或电源线导致设备down掉,所以在处理过程区间或临走时关机柜,要多观察交换机的端口是不是都是亮着的。

idea设置Spring boot工程环境变量后,启动报错(Circular placeholder reference)

1. 初始设置 2. 启动报错 Caused by: java.lang.IllegalArgumentException: Circular placeholder reference 'canal.host' in property definitions atorg.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:139) at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:160) atorg.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:124) atorg.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:237) atorg.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:211) atorg.springframework.core.env.AbstractPropertyResolver.resolveNestedPlaceholders(AbstractPropertyResolver.java:228) atorg.springframework.core.env.PropertySourcesPropertyResolver.getProperty(PropertySourcesPropertyResolver.java:88) atorg.springframework.core.env.PropertySourcesPropertyResolver.getProperty(PropertySourcesPropertyResolver.java:62) 3. 原因 properties文件中左右两边的变量名相同 4. 措施 修改properties文件,使左右两边的变量名不相同。

廖雪峰python3高阶函数部分理解

廖雪峰python3高阶函数部分理解 时间:2018年04月21日00:00:03 4.20,看了廖雪峰的python3教程,没有看太多,只看了高阶函数的map(前几天),reduce,filter,sorted函数. 总结一下: map函数,用法map(f,Inerator) f表示一个函数,Inerator表示一个迭代器,类似[1,2,3]这种可被for循环访问的,其效果为对迭代器中每一个值都执行f函数的操作,并返回一个迭代器,返回的迭代器可使用一个变量接住,后对该迭代器迭代即可取出其中的元素,也可使用list函数list(map(f,Inerator))这样就成为列表. reduce函数,初次见到这个函数,其实对它不是很理解.因为作者用了一个sum来举列子,当时还在想为什么这样浪费呢?后来发现有些玄机.reduce函数格式reduce(f,[x1,x2,x3,x4])=f(f(f(x1,x2),x3),x4),和秦九韶算法好像一样(虽然我忘了那是啥).但reduce很有用. filter函数,筛选.filter(f,Inerator)差不多,对迭代器中的元素执行f操作,如果返回结果为真,则留下,反之丢掉,和map相同,它返回也是迭代器.表示不是很懂下面的是什么. def _not_divisible(n): return lambda x: x % n >0 ​ sorted函数简单点.就接受一个key,可对排序方式进行设定sorted([1,-2,5,-9],key=abs)就是按绝对值排序 其实还看了装饰器和闭包,无奈感觉智商不够,没法理解,改日再看一遍这两个. end:2018年04月21日00:21:28 ​

python for循环条件中存在多个变量的情况

关键代码: for i,j in zip(range(5), range(4)): pass #另一种简单的形式: #enumerate将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中 #2.6以上版本可添加start参数:enumerate(sequence, [start=0]) for i, element in enumerate() pass

从request 中获取body的数据

如果在controller里直接@RequestBody就可以获取,这种方式很简单,现在说下直接从request中获取。 说下场景,我是在shiro的filter中获取body中的数据: @Override public boolean onAccessDenied(ServletRequest servletRequest, ServletResponse response) throws Exception{ log.info("into onAccessDenied"); try { HttpServletRequest httpServletRequest = (HttpServletRequest)servletRequest; String str = httpServletRequest.getQueryString(); BufferedReader bufferedReader = httpServletRequest.getReader(); String bodyStr = IOUtils.read(bufferedReader); System.out.println("bodyStr = " + bodyStr ); return true; }catch (ExpiredCredentialsException e){ log.info("请求信息过期"); WebUtils.toHttp(response).sendError(401,"请求信息过期,操作失败"); }catch (Exception e){ log.info("请求参数不合法"); e.printStackTrace(); WebUtils.toHttp(response).sendError(401,e.getMessage()); } return false; } 这里给出主要的相关代码,IOUtils是dubbo的一个类,相关依赖如下: <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.5.3</version> </dependency> 通过这种方式获取的是一个json字符串, bodyStr = { "timestamp":1523966342156 } 因为我项目中没有用到dubbo,如果为了一个body的解析引入这个感觉有些不太合适,而且启动的时候也没有正常启动,所以我把这块代码抽取了出来: package com.test.shiro.util; import java.

图片AJAX跨域请求

图片AJAX跨域请求 http://www.youhutong.com/index.php/article/index/136.html https://segmentfault.com/q/1010000011221200 https://www.zhihu.com/question/19618769 很详细多方面 https://www.zhihu.com/question/20138568 简单的说,你把Cookie托付给浏览器保存,浏览器要保证你的Cookie不被恶意网站利用。 同源策略并不能防止DDos,因为跨域的Ajax也会被请求,如果http://Evil.com用Ajax请求http://MyBank.com,浏览器会先发出请求,并且带上http://MyBank.com的Cookie。拿到http://MyBank.com的响应之后(可能有敏感数据),浏览器才会根据Header里的Access-Control-Allow-Origin决定是否把结果交给http://Evil.com里的脚本。(或者先发一个OPTIONS请求看一下CORS设置,再决定是否要发真正的请求。) 因此浏览器只是起到了最基本的防御,在写程序的时候还是要注意防御CSRF,比如关键操作不要用GET,POST请求要做额外的验证(验证码,随机数,Refer,Token)等等。 我理解你说的意思,但是同源策略的实现并不是请求不被允许,而是阻止了数据的接受。也就是说ajax的同源策略并不能阻止你的假设的情况,目标网站一样会被ddos。就说你的例子,假设12306为发送源,你的一次请求违背了同源策略,看起来是被拒绝的。但实际上,目标站接受到了请求并响应,只是响应报文被解析的时候发现违背了同源策略从而被浏览器拒绝。 posted @ 2018-04-20 17:26 Newman·Li 阅读( ...) 评论( ...) 编辑 收藏

【FPGA】基于fpga显示图片(VGA)

以640*480@60Hz分辨率显示(意思最大可以显示640*480大小的图片),首先通过fpga的VGA显示图像包括四个部分:分频模块,vga驱动模块,显示模块,顶层模块。 1.分频模块,用的是xilinx spartan_6 的板子,输出晶振50M;640*480@60Hz的时钟是25MHz(800*525*60)。就简单计数翻转分频,效果如图: 2.VGA驱动模块 显示顺序:从屏幕上到下,从左到右。 时序图:行时序分为5个进程(a.行地址复位b.行地址复位完成 准备录入数据 c.数据显示d.准备复位行地址) 场时序分为四个进程:(a.场地址复位b.场地址复位完成 准备录入数据 c.数据显示d.准备复位场地址) !!!!对于驱动部分检查,首先看时序图:一个场信号的翻转包含多个行信号(一场中扫描多行) `timescale 1ns / 1ps `define H_FRONT 11'd16 `define H_SYNC 11'd96 `define H_BACK 11'd48 `define H_DIP 11'd640 `define H_TOTAL 11'd800 `define V_FRONT 11'd10 `define V_SYNC 11'd2 `define V_BACK 11'd33 `define V_DIP 11'd480 `define V_TOTAL 11'd525 // //640*480@60hz // // module driver( clk, reset, lcd_hs, lcd_vs, lcd_en, lcd_xpos, lcd_ypos ); input clk,reset;//VGA_clk output lcd_hs,lcd_vs,lcd_en; output[10:0] lcd_xpos,lcd_ypos; wire lcd_request;

nulls first和nulls last

Nulls first和nulls last是Oracle Order by支持的语法 如果Order by 中指定了表达式Nulls first则表示null值的记录将排在最前(不管是asc 还是 desc) 如果Order by 中指定了表达式Nulls last则表示null值的记录将排在最后 (不管是asc 还是 desc) 使用语法如下: –将nulls始终放在最前 select * from zl_cbqc order by cb_ld nulls first –将nulls始终放在最后 select * from zl_cbqc order by cb_ld desc nulls last –实例 1.order by col (asc/desc) NULLS LAST 不管col如何排序 col的null(空值) 总是在最后 SQL> WITH tab AS( 2 SELECT 1 id,’小明’ NAME,’开发中心’ dept FROM dual 3 UNION ALL 4 SELECT 2,’小张’,’开发中心’ FROM dual 5 UNION ALL 6 SELECT 3,’小王’,’开发中心’ FROM dual 7 UNION ALL 8 SELECT 4,’小丽’,’研发中心’ FROM dual 9 ) 10 SELECT * 11 FROM ( 12 SELECT ID, NAME, DEPT FROM tab 13 UNION ALL 14 SELECT NULL, DEPT, DEPT FROM tab GROUP BY DEPT 15 ) 16 ORDER BY DEPT, ID NULLS LAST 17 / ID NAME DEPT

封装函数 检测数组中是否含有某个值

//封装一个函数 用于检测数组中是否含有某个值 function findValue(item,arr){ for(var i=0;i<arr.length;i++){ if(arr[i]==item){ return true; }else{ return false; } } } var numbers=["aa","bb","cc","dd","ee"]; console.log(findValue("aa",numbers));//true

封装求和函数

//封装一个求和函数 function sum(arr){ var total = 0; for (var i=0;i<arr.length;i++){ total += arr[i]; } return total; } var numbers = [-10,-2222,-35,-4]; console.log(sum(numbers));//-2217

在spring的非扫描类如何使用那些被扫描的类

今天,做了一个新功能,测试时一直报nullpointerException,原来以为是没有从数据库拿到数据,但是打了日志才发现,代码根本没有走到dao层,后来才发现是因为我在使用services层的类时,直接通过new的方式创建了对象,因为当前方法没有任何注解,所以不能自动注入,因为刚学,所以就直接new了一个对象。结果就是一直报错。后来经过别人指点,才明白。现在记录一下正确的操作。 首先,在一个service层实现中注入要使用的类,在这个service中创建一个方法关联那个不加注解的类,在方法中new不加注解的类时,将刚刚注入的对象作为参数传进去,接着再没有注解的类中声明一下需要的service的类,在创建一个有参构造器,当然参数就是所需要的类,这样经过层层传递,所需要的对象就可以用了。而不用再去new。 (1) (2) (3) (4)

python从入门到实践十二章

python编程从入门到实践12章 今天看了星球里面一位学长的经历,感到很受鼓舞,他参加工作三年了,三月份到四月份自学完了三本书,感到和学长差距很大,我要努力去弥补!决定首先开始三本书,廖雪峰的python3基础教程,python编程从入门到实践,算法图解.发现单纯的敲代码意义不大,要在敲了之后,去看书上的讲解,之后去理解代码,背代码毛用都没有.以后尽量每天都写写自己的学习经历,练好文笔,学会沟通. 第十二章主要讲了pygame模块的使用 初始化pygame.init() 创建窗口screen = pygame.display.set_mode((x,y)) 设置标题栏字样pygame.display.set_caption("name") 检查键盘鼠标行为 for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit()填充背景色screen.fill(bg_color) 刷新显示pygame.display.flip()

springBoot 项目自动编译

1.项目的pom.xml 文件中添加相应依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> 2.idea 自动编译 3.打开Registry,快捷键 ctrl+alt+shift+’/’ 4. 重启idea

Bean name用法

Spring的bean中有name属性,可以用来区分两个相同(部分属性不一样)的bean。 最近我在做influxdb多数据源的时候用到,所以这里已influxdb为示例,仅供参考。 看代码: @Bean(name = "influx1") public InfluxDB influxDB1(){ InfluxDB influxDB = InfluxDBFactory.connect("http://localhost:8086"); influxDB.setDatabase("db1") .enableBatch(20,200, TimeUnit.MILLISECONDS); return influxDB; } @Bean(name = "influx2") public InfluxDB influxDB2(){ InfluxDB influxDB = InfluxDBFactory.connect("http://localhost:8086"); influxDB.setDatabase("db2") .enableBatch(20,200, TimeUnit.MILLISECONDS); return influxDB; } 使用方式: @Resource(name = "influx1") private InfluxDB influxDB1; @Resource(name = "influx2") private InfluxDB influxDB2; 这里是在使用的地方使用@Resource注解的name属性来指定使用具体的bean。 网上有说@Autowired可以通过type之类的来获取bean的value,但是这块一直没弄好,如果有知道的朋友可以补充过来。

数数并说(Count And Say)

报数序列是指一个整数序列,按照其中的整数的顺序进行报数,得到下一个数。其前五项如下: 1. 1 2. 11 3. 21 4. 1211 5. 111221 给定一个正整数 n ,输出报数序列的第 n 项。 注意:整数顺序将表示为一个字符串。 解法一:乱糟糟版 public String countAndSay(int n) { if( n == 1) return "1"; StringBuffer start= new StringBuffer(); start.append("1"); int flag = 1; StringBuffer result = new StringBuffer(); for(int i = 1; i < n; i++){ flag = 1;//1 result.delete(0, result.length());//2 for(int j = 0;j < start.length(); j++){//3 if( j+1 < start.length() && start.charAt(j) == start.

数据分析学习笔记(三)--numpy:内置函数(通用函数、数学与统计方法、集合)

通用函数 通用函数(ufunc)是一种对ndarray中对数据执行元素级运算的函数 # 例子数组 a = np.array([-1,2.1,0.2,2.6,9.1]) # [-1. 2.1 0.2 2.6 9.1] b = np.arange(1,len(a)+1) # [1 2 3 4 5] 一元函数 函数说明例子结果abs、fabs计算整数、浮点数和复数对绝对值,对于非复数值,可以使用更快对fabsnp.abs(a)[1. 2.1 0.2 2.6 9.1]sqrt计算各元素的平方根,相当于 arr**0.5np.sqrt(b)square计算各元素的平方,相当于 arr**2np.square(b)[ 1 4 9 16 25 36 49 64 81]exp计算各元素的指数 e(x)log、log10、log2、log1p分别为自然对数(底数为e)、底数为10的log、底数为2的log、log(1+x)sign计算各元素的符号 ,1(正数)、0(零)、-1(负数)np.sign(a)[-1. 1. 1. 1. 1.]ceil向上取整np.ceil(a)[-1. 3. 1. 3. 10.]floor向下取整np.floor(a)[-1. 2. 0. 2. 9.]rint四舍五入,保留dtypenp.rint(a)[-1. 2. 0. 3. 9.]modf将元素的小数和整数部分以两个独立的数组形式返回np.modf(a)(array([-0. , 0.1, 0.2, 0.6, 0.1]), array([-1., 2., 0., 2., 9.]))nonzero将所有非零元素的行与列坐标分割开,重构成两个分别关于行和列的矩阵np.nonzero(a)(array([0, 1, 2, 3, 4]),)clip切除元素np.

phpstudy出现80端口被占用,占用进程为system

背景:公司分配的电脑是还未离职的另外一位同事。主管要求我不能重装电脑. 问题:使用这台电脑的phpstudy环境发现所调用的接口是9096端口,在站点域名配置的时候发现一个很麻烦的问题,就是在hosts文件设置127.0.0.1 www.xx.com后,直接访问www.xx.com是访问不了的,只有访问www.xx.com:9096, 但是发现页面很多资源文件没有加载。所以本人只能把它换回80端口(默认端口,一般不会出问题),通过phpstudy->phpstudy设置->常规端口设置 点击应用,重启phpstudy,发现出现80端口被占用. 查找80端口被谁占用的方法 进入命令提示行(开始运行输入 CMD),输入命令 netstat –ano ,就可以看到本机所有端口的使用情况,一般80端口在第一行,截图显示,端口已经被占用,PID 中写明 LISTENING 4。 PID=4 的程序是哪一个呢?接着在命令提示和下输入指令 tasklist ,列出所有当前运行的进程, 发现 PID=4 的进程,居然是 system 。 取消 system 进程对80端口的占用 其实本身我用的 Apache 好好的,只是突然不能启动了,回想在此期间新安装的软件,面子这么大,能让系统占用80端口的,也只能有 SQL Server 2008 了。经过查询,发现占用80端口的确是 SQL Server 2008 里面的组件——SQL Server Reporting Services (MSSQLSERVER)。是 SQL Server 的日志系统,就是他好端端的突然占用了80端口,而且对于普通人来讲,这个组件的作用没啥用,关掉也是节约资源。 关闭方法很简单,在运行框中输入 services.msc ,进入服务窗口。或者直接在开始菜单里面的搜索框中输入“服务”即可打开。然后找到 SQL Server Reporting Services (MSSQLSERVER) 这个服务,然后停止,被占用的80端口就被释放出来了。你也可以设置它的启动方式为“禁用”。 另外网上找到了另外80端口被 system 占用的原因,就是微软家的 IIS 服务,关闭方式可以去控制面板去关闭即可。 以上的操作可在在我的电脑右键->管理 然后OK~有其他问题可以留言哦~!

字符串和二维数组的互相转化

在进行前后端分离开发的时候,后端存数据需要字符串类型的数据,而前端返回和调用的多为多维数组 文本旨在说明一下,二维数组和字符串的互相转化 前端穿过来的二维数组 函数转化字段 转化后存储在一个字段内,存储的信息为 超长的一个大的字符串 当把字符串扎转换为二维数组返回给前端时候 先把大字符串,一";"为分隔符打成若干一维数组,然后该数组的每一项都打散成一个小数组,再自己设置一个数组 $keyname,作为键,和小数组合并,在遍历出来,结果就为一个二维数组 该情况适用于数组每一项的个数固定的情况

C++中replace的用法解析

replace和replaceAll是JAVA中常用的替换字符的方法,它们的区别是: 1)replace的参数是char和CharSequence,即可以支持字符的替换,也支持字符串的替换(CharSequence即字符串序列的意思,说白了也就是字符串); 2)replaceAll的参数是regex,即基于规则表达式的替换,比如,可以通过replaceAll("\\d", "*")把一个字符串所有的数字字符都换成星号; 相同点:都是全部替换,即把源字符串中的某一字符或字符串全部换成指定的字符或字符串,如果只想替换第一次出现的,可以使用replaceFirst(),这个方法也是基于规则表达式的替换,但与replaceAll()不同的是,只替换第一次出现的字符串; 另外,如果replaceAll()和replaceFirst()所用的参数据不是基于规则表达式的,则与replace()替换字符串的效果是一样的,即这两者也支持字符串的操作; 还有一点注意::执行了替换操作后,源字符串的内容是没有发生改变的。 举例如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 String src = new String( "ab43a2c43d" ); System.out.println(src.replace( "3" , "f" ));=>ab4f2c4fd. System.out.println(src.replace( '3' , 'f' ));=>ab4f2c4fd. System.out.println(src.replaceAll( "\\d" , "f" ));=>abffafcffd. System.out.println(src.replaceAll( "a" , "f" ));=>fb43fc23d. System.out.println(src.replaceFirst( "\\d," f"));=>abf32c43d System.out.println(src.replaceFirst( "4" , "h" ));=>abh32c43d. 如何将字符串中的"\"替换成"\\": ? 1 2 3 4 5 String msgIn; String msgOut; msgOut=msgIn.replaceAll( "

解决Mac 80端口被占用

在做一些第三方登录开发调试、微信小程序等开发时,必须要用本机的80端口。但是,mac却禁止了普通用户访问1024以下的端口,包括80端口,因为mac会用这些端口来提供文件共享等等很多服务。 解决办法:停掉mac自带的占用80端口的程序(其实就是一个apache),然后再设置端口转发,将80端口的请求转发到8080或9090端口。 具体操作如下: 一、关闭占用80端口的apache:sudo apachectl stop 二、修改/etc/pf.conf,设置端口转发: sudo vi /etc/pf.conf 在 rdr-anchor "com.apple/*" 后添加 rdr on lo0 inet proto tcp from any to 127.0.0.1 port 80 -> 127.0.0.1 port 8080,修改后的效果: # # Default PF configuration file. # # This file contains the main ruleset, which gets automatically loaded # at startup. PF will not be automatically enabled, however. Instead, # each component which utilizes PF is responsible for enabling and disabling # PF via -E and -X as documented in pfctl(8).