Python, Lua

Python, Lua http://blog.csdn.net/suxinpingtao51/article/details/8508428 lua最著名的应用要数魔兽争霸了,但是具体怎那么用的却不知道,实在惭愧。相对于其他语言,它最大的特点可能就是嵌入式了。其次offical的网站说是所有脚本语言里最快的,但是这也是以简单为代价的,语言简单了自然就快了,但是要实现某些功能就要写更多的代码了。再就是诸如可移植之类的就没什么好说的了,大多数脚本语言都能跨平台。似乎lua不是linux标配,但是安装比较简单,make一下就行了。 所有脚本语言的相似点: 1.基本都是以文本形式存在; 2.只需要解释,就可以直接执行,而不需要编译执行,所以可以快速开发程序的目的 (这也是这种语言产生的背景) ; 3.脚本中的变量都是无类型的,即一个变量不需要声明类型,只需要直接赋值,它既可以是字符串,也可以是整型等类型; 不同点: 脚本语言现在没有通用性,一种脚本语言可能对应一种专门的程序开发语言解释器; 在这吐槽下的是有些脚本语言版本更新后,前后变动大,导致怨声载道! lua的初衷本就是是作为一个嵌入式语言,为了这个目的,它的一切都是减无可减,拿来写大点儿的东西,就会感觉老是要自己发明轮子。比如,python方便好用的slice操作,lua就没有。 python 3的好处就是轮子基本上都发明好了,而且语言本身也有一堆语法糖让你用起来方便快捷。 但是如果项目需要一个嵌入式脚本引擎的话,我还是会选择lua的。所以lua和python基本上应用领域不冲突,有需要的话,俩都学其实也不错,并不用费多少功夫。ruby才是python的直接竞争对手。 为什么要使用脚本语言开发? 最主要有两条: 1.用它开发快捷和高效,如相同的功能用Python 50行代码,用C++也许要500行,用Java也许要200行; 2.python又可以叫作胶水语言,可以把C++、Java写的模块轻松粘到起来一协同工作;如Python写的模块,用Java或C++也能够非常方便的调用,反过来调用也可以; 买了本lua程序设计,准备对比python学lua,下面写点东西记录一下: 第一章: 1.1 程序块: lua不是以缩进区分程序块的,这和python有很大区别,lua以end结束一个程序块。 1.2 词法规范: 没什么好说的,C为单行注释,python里单行注释用#,lua的多行注释以C[[开头,]]结尾,注意第一个C和后面的[[没有空格,python里没有多行注释,如果需要多行注释一般使用三引号。 1.3 全局变量: lua和python一样,变量都不需要声明,直接赋值就可以了,但是删除的时候有点区别,lua用nil赋值变量达到删除变量的目的,而python用del调用来删除变量或者把变量赋值None。 1.4 解释器程序: 没什么可对比的,都有交互的解释器,用于语言的学习不错。lua的解释器启动的时候有几个参数,-e后面接要执行的code,这个MySQL的-e参数一样,-i是运行完code之后进入交互模式,还有一个环境变量来_PROMPT保存提示符。 lua的命令行参数用arg来引用,可以使用负索引,0是文件本身,python使用sys.argv存储命令行参数,和lua一样,0表示文件本身,但是不可以使用负索引。第二章: 2.1 nil: lua中变量有两种状态,非nil状态和nil状态,未定义以前都是nil,python只有定义了才能用。nil在lua中表示一切异常值,python用None表示。 2.2 boolean: lua里只有false和nil是假,其他一概为真,这个python有区别,python里空串和空list都算假。 2.3 number: lua里只有浮点数,没有证书类型,python里区分int和float。 2.4 string: lua和python一样,不能修改字符串,值能创建新的字符串,lua里多行字符串使用[[和]],这里还有一个小技巧,在两个[[之间加入等号,后面再的两个]]在放入数量相同的等号,可以匹配,这是为了避免字符串里出现[[和]],python里多行字符串使用三引号。lua里字符串和数字会自动转换,python不能自动转换,要转换需要调用函数。lua里使用#操作符取长度,python使用len()。lua中字符串链接使用..,python使用加号。 2.5 table: lua里的table和python里的dict比较像,使用方法类似,需要注意的是#取table长度的时候,不能有"空洞",否则可能取到的不是期望值。另外需要注意的一个重要缓解是,lua中默认以1为索引的开始,而python是从0开始的,这个区别非常重要,lua里很多默认函数的实现也依赖于这个默认约定,所以学lua的时候最好注意索引的起点。 2.6 function: lua里function和普通变量一样对待,python里则把一切看作对象。 2.7 userdata和thread: 后面有详细说明,在此先不做说明。

2015-07-27 · 1 min · 58 words · -

Redis

Redis REmote DIctionary Server(Redis) 是一个由SalvatoreSanfilippo写的key-value存储系统。 Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工作由VMware主持。从2013年5月开始,Redis的开发由Pivotal赞助。redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hash (哈希类型) 。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了 master-slave (主从)同步。 Redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部分场合可以对关系数据库起到很好的补充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客户端,使用很方便。 Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。存盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助。 redis的官网地址,非常好记,是redis.io。 (特意查了一下,域名后缀io属于国家域名,是british Indian Ocean territory,即英属印度洋领地) 目前,Vmware在资助着redis项目的开发和维护。redis[2] 的作者,叫Salvatore Sanfilippo,来自意大利的西西里岛,现在居住在卡塔尼亚。目前供职于Pivotal公司。他使用的网名是antirez。 Redis 4.0 之后的版本,情况就有了一些变动,新版的 Redis 服务在执行一些命令时就会使用『主处理线程』之外的其他线程,例如 UNLINK、FLUSHALL ASYNC, FLUSHDB ASYNC 等非阻塞的删除操作。 Redis 在较新的版本中引入了多线程,不过是在部分命令上引入的,其中包括非阻塞的删除操作,在整体的架构设计上,主处理程序还是单线程模型的 线程模型 使用单线程模型能带来更好的可维护性,方便开发和调试; 使用单线程模型也能并发的处理客户端的请求; Redis 服务中运行的绝大多数操作的性能瓶颈都不是 CPU 6.0 Redis 的多线程部分只是用来处理网络数据的读写和协议解析,执行命令仍然是单线程。之所以这么设计是不想因为多线程而变得复杂 I/O 多路复用的主要作用是让我们可以使用一个线程来监控多个连接是否可读或者可写,但是从网络另一头发的数据包需要先解序列化成 Redis 内部其他模块可以理解的命令,这个过程就是 Redis 6.0 引入多线程来并发处理的。 I/O 多路复用模块收到数据包之后将其丢给后面多个 I/O 线程进行解析,I/O 线程处理结束后,主线程会负责串行的执行这些命令,由于向客户端发回数据包的过程也是比较耗时的,所以执行之后的结果也会交给多个 I/O 线程发送回客户端。 AOF AOF 是 Redis 的一种持久化机制,它会在每次收到来自客户端的写请求时,将其记录到日志中,每次 Redis 服务器启动时都会重放 AOF 日志构建原始的数据集,保证数据的持久性。 Keyspace Notifications, 键空间通知 在Redis2.8.0版本的时候,推出 Keyspace Notifications future。 Keyspace Notifications 此特性允许客户端可以以 订阅/发布 (Sub/Pub) 模式,接收那些对数据库中的键和值有影响的操作事件。这些操作事件具体来说,就是 hash , del, expire , set , lpop 等。 那么你可能会问,redis keyspace 到底有啥用处? 简单说,对于我个人主要关注keyspace几个扩展场景: ...

2015-07-13 · 2 min · 357 words · -

PPT模板中的背景图片如何修改

PPT模板中的背景图片如何修改 power point 2003/2012 ,打开模板后,进入"视图"菜单下的"母版",再进入下一级"幻灯片母版",单击,就可以修改模板的母版 for English version, view > slide master.

2015-07-09 · 1 min · 12 words · -

线程

线程 进程在各自独立的空间中运行,进程之间共享数据需要用 mmap 或者进程间通信机制 (IPC) 如何在一个进程空间中执行多个线程,有些情况需要在一个进程中同时执行多个控制流程,这时候线程就派上了用场, 线程是比进程更轻量级的调度执行单位,线程的引入可以把一个进程的资源分配和执行调度分开,各个线程既可以共享进程资源(内存地址,文件IO等),又可以独立调度 (线程是CPU调度的基本单位) 。 线程共享以下进程的资源和环境 文件描述符表 (重点) 每种信号的处理方式 (SIG_IGN、SIG_DFL或者自定义的信号处理函数) 当前工作目录 用户id和组id 线程有自己的私有数据 线程id 上下文信息, 包括各种寄存器的值, 程序计数器, 栈指针 栈空间 (临时变量存储在栈空间中) (重点) errno变量 信号屏蔽字 调度优先级 Linux上线程位于libpthread共享库中,因此在编译时要加上-lpthread选项 (-l :指明所链接的库) 进程与线程的联系与区别 线程是在进程内部运行的执行分支 线程是为了资源共享 (共享地址空间) ,进程是为了资源独占 (私有地址空间) Linux下没有真正的线程,它是利用轻量级进程来代替实现的 进程是分配资源 (资源管理) 的最小单元;而线程是调度资源 (程序执行) 的最小单元 线程与线程之间是独立的 实现线程主要有三种方式: 使用内核线程实现,使用用户线程实现和使用用户线程加轻量级进程混合实现。 java thread Thread Dump日志的线程信息 "resin-22129" daemon prio=10 tid=0x00007fbe5c34e000 nid=0x4cb1 waiting on condition [0x00007fbe4ff7c000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:315) at com.caucho.env.thread2.ResinThread2.park(ResinThread2.java:196) at com.caucho.env.thread2.ResinThread2.runTasks(ResinThread2.java:147) at com.caucho.env.thread2.ResinThread2.run(ResinThread2.java:118) "Timer-20" daemon prio=10 tid=0x00007fe3a4bfb800 nid=0x1a31 in Object.wait() [0x00007fe3a077a000] java.lang.Thread.State: TIMED_WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x00000006f0620ff0> (a java.util.TaskQueue) at java.util.TimerThread.mainLoop(Timer.java:552) - locked <0x00000006f0620ff0> (a java.util.TaskQueue) at java.util.TimerThread.run(Timer.java:505) 以上依次是: ...

2015-06-30 · 6 min · 1102 words · -

CPU

CPU CPU执行过的指令都遵循以下的流程: CPU首先依据指令指针取得(Fetch)将要执行的指令在代码段的地址,接下来解码(Decode)地址上的指令。解码之后,会进入真正的执行(Execute)阶段,之后会是"写回"(Write Back)阶段,将处理的最终结果写回内存或寄存器中,并更新指令指针寄存器指向下一条指令。 1982年,处理器中引入了指令缓存。 1989年,i486处理器引入了五级流水线。 1995年Intel发布Pentium Pro处理器时,加入了乱序执行核心(Out-of-order core, OOO core)。 乱序执行也并不一定100%达到顺序执行代码的效果。有些时候确实需要引入内存屏障来确保执行的先后顺序。 http://www.infoq.com/cn/articles/x86-high-performance-programming-pipeline?utm_campaign=infoq_content&utm_source=infoq&utm_medium=feed&utm_term=global 乱序执行 乱序执行 vs 顺序提交 我们知道,在cpu中为了能够让指令的执行尽可能地并行起来,从而发明了流水线技术。但是如果两条指令的前后存在依赖关系,比如数据依赖,控制依赖等,此时后一条语句就必需等到前一条指令完成后,才能开始。 cpu为了提高流水线的运行效率,会做出比如: 1)对无依赖的前后指令做适当的乱序和调度;2)对控制依赖的指令做分支预测;3)对读取内存等的耗时操作,做提前预读;等等。以上总总,都会导致指令乱序的可能。 指令在cpu核内部确实是乱序执行和调度的,但是它们对外表现却是顺序提交的。 Store Buffer https://zhuanlan.zhihu.com/p/141655129 store buffer是什么 在之前的文章介绍中,我们了解到每个CPU都会有自己私有L1 Cache。从我了解的资料来说,L1 Cache命中的情况下,访问数据一般需要2个指令周期。而且当CPU遭遇写数据cache未命中时,内存访问延迟增加很多。硬件工程师为了追求极致的性能,在CPU和L1 Cache之间又加入一级缓存,我们称之为store buffer。store buffer和L1 Cache还有点区别,store buffer只缓存CPU的写操作。store buffer访问一般只需要1个指令周期,这在一定程度上降低了内存写延迟。不管cache是否命中,CPU都是将数据写入store buffer。store buffer负责后续以FIFO次序写入L1 Cache。store buffer大小一般只有几十个字节。大小和L1 Cache相比,确实是小巫见大巫了。 Invalid Queue 超线程 超线程技术就是利用特殊的硬件指令,把一个物理芯片模拟成两个逻辑处理核心,让单个处理器都能使用线程级并行计算,进而兼容多线程操作系统和软件,减少了CPU的闲置时间,提高的CPU的运行效率。这种超线程技术(如双核四线程)由处理器硬件的决定,同时也需要操作系统的支持才能在计算机中表现出来 https://www.cnblogs.com/Survivalist/p/11527949.html ‘查CPU, 核心数’ lscpu cat /proc/cpuinfo |grep name # 总核数 = 物理CPU个数 X 每颗物理CPU的核数 # 总逻辑CPU数 = 物理CPU个数 X 每颗物理CPU的核数 X 超线程数 # 查看物理CPU个数 cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l # 查看每个物理CPU中core的个数(即核数) cat /proc/cpuinfo| grep "cpu cores"| uniq # 查看逻辑CPU的个数 cat /proc/cpuinfo| grep "processor"| wc -l grep 'model name' /proc/cpuinfo | wc -l Intel CPU Cascade Lake 第二代智能英特尔® 至强® 可扩展处理器,前身为 Cascade Lake,搭载英特尔® C620 系列芯片组(前身为 Purley refresh), 配有内置英特尔® 深度学习加速(英特尔® DL Boost),可针对人工智能工作负载提供高性能推断和视觉。它可整合多元化的物联网工作负载、处理海量数据集并支持接近实时的交易。现在,借助英特尔® Distribution of OpenVINO™ Toolkit 等已进行 CPU 优化的软件工具套件和框架,您可以获得更好的内置深度学习功能,加快部署速度,并降低总拥有成本 (TCO)。 ...

2015-06-30 · 1 min · 140 words · -

丢失更新, 脏读、幻读和不可重复读

丢失更新, 脏读、幻读和不可重复读 http://uule.iteye.com/blog/1109647 脏读、幻读和不可重复读 + 事务隔离级别 博客分类: 数据库 需学习 ITeyeBlog.net 丢失更新: 两个事务同时更新一行数据,最后一个事务的更新会覆盖掉第一个事务的更新,从而导致第一个事务更新的数据丢失,这是由于没有加锁造成的; 脏读 : 脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。 e.g. 1.Mary的原工资为1000, 财务人员将Mary的工资改为了8000(但未提交事务) 2.Mary读取自己的工资 ,发现自己的工资变为了8000,欢天喜地! 3.而财务发现操作有误,回滚了事务,Mary的工资又变为了1000 像这样,Mary记取的工资数8000是一个脏数据。 不可重复读 : 是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。 e.g. 1.在事务1中,Mary 读取了自己的工资为1000,操作并没有完成 2.在事务2中,这时财务人员修改了Mary的工资为2000,并提交了事务. 3.在事务1中,Mary 再次读取自己的工资时,工资变为了2000 解决办法: 如果只有在修改事务完全提交之后才可以读取数据,则可以避免该问题。 幻读 : 是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。 e.g. 目前工资为1000的员工有10人。 1.事务1,读取所有工资为1000的员工。 2.这时事务2向employee表插入了一条员工记录,工资也为1000 3.事务1再次读取所有工资为1000的员工 共读取到了11条记录, 解决办法: 如果在操作事务完成数据处理之前,任何其他事务都不可以添加新数据,则可避免该问题 不可重复读的重点是修改 : 同样的条件, 你读取过的数据,再次读取出来发现值不一样了 幻读的重点在于新增或者删除 同样的条件, 第 1 次和第 2 次读出来的记录数不一样 参考: http://cupoy.iteye.com/blog/251796 http://blog.csdn.net/d8111/archive/2008/06/29/2595635.aspx http://www.iteye.com/topic/332577 在一个程序中,依据事务的隔离级别将会有三种情况发生。 ◆脏读: 一个事务会读进还没有被另一个事务提交的数据,所以你会看到一些最后被另一个事务回滚掉的数据。 ◆不可重复读: 一个事务读进一条记录,另一个事务更改了这条记录并提交完毕,这时候第一个事务再次读这条记录时,它已经改变了。 ◆ 幻影读: 一个事务用Where子句来检索一个表的数据,另一个事务插入一条新的记录,并且符合Where条件,这样,第一个事务用同一个where条件来检索数据后,就会多出一条记录。 数据库提供了四种事务隔离级别, 不同的隔离级别采用不同的锁类开来实现. 在四种隔离级别中, Serializable的级别最高, Read Uncommited级别最低. ...

2015-06-28 · 1 min · 149 words · -

java transient

java transient http://www.cnblogs.com/lanxuezaipiao/p/3369962.html 我们都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化, java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过程,只要这个类实现了Serilizable接口,这个类的所有属性和方法都会自动序列化。 然而在实际开发过程中,我们常常会遇到这样的问题,这个类的有些属性需要序列化,而其他属性不需要被序列化,打个比方,如果一个用户有一些敏感信息 (如密码,银行卡号等) ,为了安全起见,不希望在网络操作 (主要涉及到序列化操作,本地序列化缓存也适用) 中被传输,这些信息对应的变量就可以加上transient关键字。换句话说,这个字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化。 总之,java 的transient关键字为我们提供了便利,你只需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。 一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。 transient 关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。 被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。 第三点可能有些人很迷惑,因为发现在User类中的username字段前加上static关键字后,程序运行结果依然不变,即static类型的username也读出来为"Alexia"了,这不与第三点说的矛盾吗?实际上是这样的: 第三点确实没错 (一个静态变量不管是否被transient修饰,均不能被序列化) ,反序列化后类中static型变量username的值为当前JVM中对应static变量的值,这个值是JVM中的不是反序列化得出的, 我们知道在Java中,对象的序列化可以通过实现两种接口来实现,若实现的是Serializable接口,则所有的序列化将会自动进行,若实现的是Externalizable接口,则没有任何东西可以自动序列化,需要在writeExternal方法中进行手工指定所要序列化的变量,这与是否被transient修饰无关。因此第二个例子输出的是变量content初始化的内容,而不是null。

2015-06-28 · 1 min · 21 words · -

时间复杂度, time complexity, 大O符号

时间复杂度, time complexity, 大O符号 时间复杂度, time complexity 大O符号, Big O notation O(log n) 时间复杂度 O(log n) 意味着什么? 原文链接: github.com 原文地址: What does the time complexity O(log n) actually mean? 原文作者: Maaz 译文出自: 掘金翻译计划 译者: cdpath 校对者: zaraguo (zaraguo), whatbeg (Qiu Hu) 预先知道算法的复杂度是一回事,了解其后的原理是另一件事情。 不管你是计算机科班出身还是想有效解决最优化问题,如果想要用自己的知识解决实际问题,你都必须理解时间复杂度。 先从简单直观的 O(1) 和 O(n) 复杂度说起。O(1) 表示一次操作即可直接取得目标元素 (比如字典或哈希表) ,O(n) 意味着先要检查 n 个元素来搜索目标,但是 O(log n) 是什么意思呢? 你第一次听说 O(log n) 时间复杂度可能是在学二分搜索算法的时候。二分搜索一定有某种行为使其时间复杂度为 log n。我们来看看是二分搜索是如何实现的。 因为在最好情况下二分搜索的时间复杂度是 O(1),最坏情况 (平均情况) 下 O(log n),我们直接来看最坏情况下的例子。已知有 16 个元素的有序数组。 ...

2015-06-28 · 1 min · 106 words · -

密码,哈希,加盐 Adding Salt

加密哈希函数 SHA256,SHA512,RipeMD, WHIRLPOOL, Bcrypt wiloon.com/bcrypt 什么是密码哈希函数? A 密码哈希函数 是一组散列函数之一,适用于SSL /TLS。 像其他哈希函数一样,密码哈希函数是一种单向数学算法,用于将任何大小的数据映射到固定大小的位字符串。 加密哈希函数广泛用于信息安全实践中,例如数字签名,消息身份验证代码和其他形式的身份验证。 加密哈希函数应具有以下属性 (来源: 维基百科): 1.相同的消息始终导致相同的哈希值 (即,函数为 确定性). 2.快速计算哈希值。 3.具有相同散列值的两个消息 (称为“冲突”)是不可行的。 4.故意创建产生给定哈希值的消息是不可行的。 5.对消息的轻微更改应在很大​​程度上更改所得的哈希值,以使其看起来与原始哈希不相关。 最常用的加密哈希函数包括MD5,SHA-1和SHA-2。 每个哈希的唯一性对于密码哈希功能的完整性至关重要。 这才是真正将密码哈希函数与其他哈希函数区分开的地方-确保以唯一且不可复制的方式识别特定消息。 数字签名方案 (例如 文件签署, 代码签名或 S/MIME 邮箱地址)通常要求对消息进行加密哈希计算并包含在签名中。 然后,收件人的软件将独立计算哈希值,以验证邮件的完整性。 网站还经常发布可下载文件的哈希值。 用户下载文件时,可以使用自己的软件独立计算哈希值,从而验证文件的完整性。 密码安全性还依赖于加密哈希。 用户提供的密码被散列,然后与存储的散列进行比较。 加密哈希函数广泛用于安全协议,例如 SSL /TLS 和SSH,以及其他依赖数据完整性的应用程序。 加密货币使用哈希算法来使用新的安全可验证交易数据块更新区块链。 (例如,BitCoin使用SHA-2进行交易验证。) 什么是SHA-1? SHA-1 (安全哈希算法1) 是一种加密哈希函数,可以将任意长的数据字符串转换为固定大小为160位的摘要。 该摘要通常显示为40个字符的十六进制数字。 SHA-1算法现已推出 被认为是不安全的。 SHA-1证书不再符合CA / B论坛基准要求,或不再受当前主要Web浏览器版本的支持。 安全哈希算法 (SHA)系列哈希函数由不同的集合 (SHA-0,SHA-1,SHA-2,SHA-3)组成。 什么是SHA-2? SHA-2 (安全哈希算法2) “加密”是指可以将任意长数据串转换为固定大小 (224、256、384或512位)摘要的加密哈希函数系列。 256位SHA-2,也称为 SHA-256,是最常用的版本。 摘要通常显示为固定值的十六进制数。 (例如,SHA-256返回64个字符的代码。) SHA-2在安全协议 (例如SSL /TLS. 查表法 查表法对于破解一系列算法相同的哈希值有着无与伦比的效率。主要的思想就是预计算密码字典中的每个密码,然后把哈希值和对应的密码储存到一个用于快速查询的数据结构中。一个良好的查表实现可以每秒进行数百次哈希查询,即使表中储存了几十亿个哈希值。 ...

2015-06-28 · 2 min · 247 words · -

MySQL 存储引擎 Memory

MySQL 存储引擎 Memory http://samyubw.blog.51cto.com/978243/223769 Memory存储引擎使用存在内存中的内容来创建表,每个Memory表只实际对应一个磁盘文件,在磁盘中表现为.frm文件。Memory类型的表访问速度非常快,因为它的数据是放在内存中的,并且默认使用hash索引,但是一旦服务关闭,表中的数据就会丢失。 示例: create table memory_tab(id int)engine=memory; 因为memory在MySQLd重启后数据就会丢失,为了获得稳定的数据源,可以在启动MySQLd时加上—init-file选项,把insert into memory_tab select 或load data infile类似的语句放进去即可。 另外因为memory表是把数据放到内存中的,所以服务器需要有足够的内存来维持所有在同一时间使用的memory表,注意对连接MySQLd的所有用户连接 共享 内存表中的数据,根据应用如果不是在所有连接间共享数据,最好在内存表中加入标志各个连接的ID。当不再需要memory数据时,要记得去删除自己连接的数据。 对于内存表的官方说明: The MEMORY storage engine creates tables with contents that are stored in memory. Formerly, these were known as HEAP tables. MEMORY is the preferred term, although HEAP remains supported for backward compatibility. Each MEMORY table is associated with one disk file. The filename begins with the table name and has an extension of .frm to indicate that it stores the table definition. ...

2015-06-28 · 1 min · 196 words · -

MySQL 存储引擎

MySQL 存储引擎 什么是存储引擎? 关系数据库表是用于存储和组织信息的数据结构,可以将表理解为由行和列组成的表格,类似于Excel的电子表格的形式。有的表简单,有的表复杂,有的表根本不用来存储任何长期的数据,有的表读取时非常快,但是插入数据时去很差;而我们在实际开发过程中,就可能需要各种各样的表,不同的表,就意味着存储不同类型的数据,数据的处理上也会存在着差异,那么。对于MySQL来说,它提供了很多种类型的存储引擎,我们可以根据对数据处理的需求,选择不同的存储引擎,从而最大限度的利用MySQL强大的功能。这篇博文将总结和分析各个引擎的特点,以及适用场合,并不会纠结于更深层次的东西。我的学习方法是先学会用,懂得怎么用,再去知道到底是如何能用的。下面就对MySQL支持的存储引擎进行简单的介绍。 MyISAM MyISAM 发音为 “my-z[ei]m”; 在MySQL客户端中,使用以下命令可以查看MySQL支持的引擎:show engines; MyISAM表是独立于操作系统的,这说明可以轻松地将其从Windows服务器移植到Linux服务器;每当我们建立一个MyISAM引擎的表时,就会在本地磁盘上建立三个文件,文件名就是表明。例如,我建立了一个MyISAM引擎的tb_Demo表,那么就会生成以下三个文件: tb_demo.frm,存储表定义; tb_demo.MYD,存储数据; tb_demo.MYI,存储索引。 MyISAM表无法处理事务,这就意味着有事务处理需求的表,不能使用MyISAM存储引擎。MyISAM存储引擎特别适合在以下几种情况下使用: 选择密集型的表。MyISAM存储引擎在筛选大量数据时非常迅速,这是它最突出的优点。 插入密集型的表。MyISAM的并发插入特性允许同时选择和插入数据。例如: MyISAM存储引擎很适合管理邮件或Web服务器日志数据。 InnoDB InnoDB是一个健壮的事务型存储引擎,这种存储引擎已经被很多互联网公司使用,为用户操作非常大的数据存储提供了一个强大的解决方案。我的电脑上安装的MySQL 5.6.13版,InnoDB就是作为默认的存储引擎。InnoDB还引入了行级锁定和外键约束,在以下场合下,使用InnoDB是最理想的选择: 更新密集的表。InnoDB存储引擎特别适合处理多重并发的更新请求。 事务。InnoDB存储引擎是支持事务的标准MySQL存储引擎。 自动灾难恢复。与其它存储引擎不同,InnoDB表能够自动从灾难中恢复。 外键约束。MySQL支持外键的存储引擎只有InnoDB。 支持自动增加列AUTO_INCREMENT属性。 一般来说,如果需要事务支持,并且有较高的并发读取频率,InnoDB是不错的选择。 MEMORY 使用MySQL Memory存储引擎的出发点是速度。为得到最快的响应时间,采用的逻辑存储介质是系统内存。虽然在内存中存储表数据确实会提供很高的性能,但当MySQLd守护进程崩溃时,所有的Memory数据都会丢失。获得速度的同时也带来了一些缺陷。它要求存储在Memory数据表里的数据使用的是长度不变的格式,这意味着不能使用BLOB和TEXT这样的长度可变的数据类型,VARCHAR是一种长度可变的类型,但因为它在MySQL内部当做长度固定不变的CHAR类型,所以可以使用。 一般在以下几种情况下使用Memory存储引擎: 目标数据较小,而且被非常频繁地访问。在内存中存放数据,所以会造成内存的使用,可以通过参数max_heap_table_size控制Memory表的大小,设置此参数,就可以限制Memory表的最大大小。 如果数据是临时的,而且要求必须立即可用,那么就可以存放在内存表中。 存储在Memory表中的数据如果突然丢失,不会对应用服务产生实质的负面影响。 Memory同时支持散列索引和B树索引。B树索引的优于散列索引的是,可以使用部分查询和通配查询,也可以使用<、>和>=等操作符方便数据挖掘。散列索引进行"相等比较"非常快,但是对"范围比较"的速度就慢多了,因此散列索引值适合使用在=和<>的操作符中,不适合在<或>操作符中,也同样不适合用在order by子句中。 可以在表创建时利用USING子句指定要使用的版本。例如: create table users ( id smallint unsigned not null auto_increment, username varchar(15) not null, pwd varchar(15) not null, index using hash (username), primary key (id) )engine=memory; 上述代码创建了一个表,在username字段上使用了HASH散列索引。下面的代码就创建一个表,使用BTREE索引。 create table users ( id smallint unsigned not null auto_increment, ...

2015-06-28 · 2 min · 405 words · -

MemCache

MemCache http://blog.csdn.net/hjm4702192/article/details/7894080 Memcach什么是Memcache Memcache集群环境下缓存解决方案 Memcache是一个高性能的分布式的内存对象缓存系统,通过在内存里维护一个统一的巨大的hash表,它能够用来存储各种格式的数据,包括图像、视频、文件以及数据库检索的结果等。简单的说就是将数据调用到内存中,然后从内存中读取,从而大大提高读取速度。 Memcache是danga的一个项目,最早是LiveJournal 服务的,最初为了加速 LiveJournal 访问速度而开发的,后来被很多大型的网站采用。 Memcached是以守护程序方式运行于一个或多个服务器中,随时会接收客户端的连接和操作 为什么会有Memcache和memcached两种名称 其实Memcache是这个项目的名称,而memcached是它服务器端的主程序文件名,知道我的意思了吧。一个是项目名称,一个是主程序文件名,在网上看到了很多人不明白,于是混用了。 Memcached是高性能的,分布式的内存对象缓存系统,用于在动态应用中减少数据库负载,提升访问速度。Memcached由Danga Interactive开发,用于提升LiveJournal.com访问速度的。LJ每秒动态页面访问量几千次,用户700万。Memcached将数据库负载大幅度降低,更好的分配资源,更快速访问。 上网baidu了很多东西,几乎都差不多,而且基于java的说的很少,所有只有在研究了各个其他语言类的应用后再来尝试在java上进行简单的操作应用。先从memcached上进行说明,memcached的最新版是采用c语言进行开发和设计的,据说旧版的是采用perl语言开发的,而且它是一个应用软件来的,是作为缓存服务器的服务器端运行在服务器上的,需要使用特定的语言编写客户端与其进行通信来进行数据的缓存和获取。通常我们是把memcached安装运行在web服务器上,然后通过对需要的数据进行缓存,据我目前所知,所有数据的缓存设置和存取操作,以及数据的更新后替换操作全部需要程序来进行,而不是自动进行的 (自动不知道能不能成功,呵呵) 。下面从一个实际的例子来应用memcached。 如何要下载的话,到http://danga.com/memcached/下载memcached。 Ubuntu下安装Memcached 编译前,请先确认gcc、make、patch等编译工具是否已安装,并可正常使用。 安装Libevent Libevent是一个异步事件处理软件函式库,以BSD许可证释出。Memcached依赖Libevent,因此必须先编译安装Libevent。 检测libevent 安装是否成功,输入: # ls -al /usr/lib | grep libevent 会出现如下结果 (不同的机器可能有不同的输出) : yangfei@yangfei-laptop:~$ ls -al /usr/lib |grep libevent lrwxrwxrwx 1 root root 21 2009-07-19 08:45 libevent-1.4.so.2 -> libevent-1.4.so.2.1.3 -rwxr-xr-x 1 root root 301588 2009-07-19 08:45 libevent-1.4.so.2.1.3 -rw-r-r- 1 root root 386638 2009-07-19 08:45 libevent.a lrwxrwxrwx 1 root root 26 2009-07-19 08:45 libevent_core-1.4.so.2 -> libevent_core-1.4.so.2.1.3 ...

2015-06-28 · 11 min · 2184 words · -

缓存算法, LFU, LRU, FIFO

缓存算法, LFU, LRU, FIFO 超时剔除 - expire 主动更新 - 开发控制生命周期 扩展: 缓存污染 - 缓存污染降低了缓存的使用率,把不常用的数据读取到缓存,同时会把常用的数据移出缓存,这样会直接降低系统的数据命中率 http://www.leexiang.com/cache-algorithm 缓存算法 原文: http://www.jtraining.com/component/content/article/35-jtraining-blog/98.html 翻译: http://www.zavakid.com/25 引言 我们都听过 cache,当你问他们是什么是缓存的时候,他们会给你一个完美的答案,可是他们不知道缓存是怎么构建的,或者没有告诉你应该采用什么标准去选择缓存框架。在这边文章,我们会去讨论缓存,缓存算法,缓存框架以及哪个缓存框架会更好。 “缓存就是存贮数据 (使用频繁的数据) 的临时地方,因为取原始数据的代价太大了,所以我可以取得快一些。” 这就是 programmer one (programmer one 是一个面试者) 在面试中的回答 (一个月前,他向公司提交了简历,想要应聘要求在缓存,缓存框架,大规模数据操作有着丰富经验的 java 开发职位) 。 programmer one 通过 hash table 实现了他自己的缓存,但是他知道的只是他的缓存和他那存储着150条记录的 hash table,这就是他认为的大规模数据 (缓存 = hashtable,只需要在 hash table 查找就好了) ,所以,让我们来看看面试的过程吧。 面试官: 你选择的缓存方案,是基于什么标准的? programmer one: 呃, (想了5分钟) 嗯,基于,基于,基于数据 (咳嗽……) 面试官: excese me ! 能不能重复一下? programmer one: 数据?! 面试官: 好的。说说几种缓存算法以及它们的作用 programmer one: (凝视着面试官,脸上露出了很奇怪的表情,没有人知道原来人类可以做出这种表情 ) ...

2015-06-28 · 6 min · 1249 words · -

Redis, Memcache, Guava, Ehcache 中的算法

Redis, Memcache, Guava, Ehcache 中的算法 缓存那些事,一是内存爆了要用LRU(最近最少使用, Least Recently Used)、LFU(最少访问次数, Least Frequently Used)、FIFO的算法清理一些;二是设置了超时时间的键过期便要删除,用主动或惰性的方法。 在看所有的细节之前,可以看一篇相当专业的《缓存算法》,世界真宽阔,算法真奇妙。 LRU 简单粗暴的Redis 今天看Redis3.0的发行通告里说,LRU算法大幅提升了,就翻开源码来八卦一下,结果哭笑不得,这旧版的"近似LRU"算法,实在太简单,太偷懒,太Redis了。 在Github的Redis项目里搜索lru,找到代码在redis.c的freeMemoryIfNeeded()函数里。 先看2.6版的代码: 竟然就是随机找三条记录出来,比较哪条空闲时间最长就删哪条,然后再随机三条出来,一直删到内存足够放下新记录为止…….可怜我看配置文档后的想象,一直以为它会帮我在整个Redis里找空闲时间最长的,哪想到我有一百万条记录的时候,它随便找三条就开始删了。 好,收拾心情再看3.0版的改进: 现在每次随机五条记录出来,插入到一个长度为十六的按空闲时间排序的队列里,然后把排头的那条删掉,然后再找五条出来,继续尝试插入队列………嗯,好了一点点吧,起码每次随机多了两条,起码不只在一次随机的五条里面找最久那条,会连同之前的一起做比较…… 中规中矩的Memcached 相比之下,Memcached实现的是再标准不过的LRU算法,专门使用了一个教科书式的双向链表来存储slab内的LRU关系,代码在item.c里,详见memcached源码分析–LRU队列与item结构体,元素插入时把自己放到列头,删除时把自己的前后两个元素对接起来,更新时先做删除再做插入。 分配内存超限时,很自然就会从LRU的队尾开始清理。 同样中规中矩的Guava Cache Guava Cache同样做了一个双向的Queue,见LocalCache中的AccessQueue类,也会在超限时从Queue的队尾清理,见evictEntries()函数。 和Redis旧版一样的Ehcache/Hazelcast 看文档,居然和Redis2.6一样,直接随机8条记录,找出最旧那条,刷到磁盘里,再看代码,Eviction类 和 OnHeapStore的evict()函数。 再看Hazelcast,几乎一样,随机取25条。 这种算法,切换到LFU也非常简单。 小结 不过后来再想想,也许Redis本来就不是主打做Cache的,这种内存爆了需要通过LRU删掉一些元素不是它的主要功能,默认设置都是noeviction——内存不够直接报错的,所以就懒得建个双向链表,而且每次访问时都要更新它了,看Google Group里长长的讨论,新版算法也是社区智慧的结晶。何况,Ehcache和Hazelcast也是和它的旧版一样的算法,Redis的新版还比这两者强了。 后来,根据@刘少壮同学的提示,JBoss的InfiniSpan里还实现了比LRU更高级的LIRS算法,可以避免一些冷数据因为某个原因被大量访问后,把热数据挤占掉。 过期键删除 如果能为每一个设置了过期的元素启动一个Timer,一到时间就触发把它删掉,那无疑是能最快删除过期键最省空间的,在Java里用一条DeplayQueue存着,开条线程不断的读取就能做到。但因为该线程消耗CPU较多,在内存不紧张时有点浪费,似乎大家都不用这个方法。 所以有了惰性检查,就是每次元素被访问时,才去检查它是否已经超时了,这个各家都一样。但如果那个元素后来都没再被访问呢,会永远占着位子吗?所以各家都再提供了一个定期主动删除的方式。 Redis 代码在redis.c的activeExpireCycle()里,看过文档的人都知道,它会在主线程里,每100毫秒执行一次,每次随机抽20条Key检查,如果有1/4的键过期了,证明此时过期的键可能比较多,就不等100毫秒,立刻开始下一轮的检查。不过为免把CPU时间都占了,又限定每轮的总执行时间不超过1毫秒。 Memcached Memcached里有个文不对题的LRU爬虫线程,利用了之前那条LRU的队列,可以设置多久跑一次(默认也是100毫秒),沿着列尾一直检查过去,每次检查LRU队列中的N条数据。虽然每条Key设置的过期时间可能不一样,但怎么说命中率也比Redis的随机选择N条数据好一点,但它没有Redis那种过期的多了立马展开下一轮检查的功能,所以每秒最多只能检查10N条数据,需要自己自己权衡N的设置。 Guava Cache 在Guava Cache里,同一个Cache里所有元素的过期时间是一样的,所以它比Memached更方便,顺着之前那条LRU的Queue检查超时,不限定个数,直到不超时为止。而且它这个检查的调用时机并不是100毫秒什么的,而是每次各种写入数据时的preWriteCleanup()方法中都会调用。 吐槽一句,Guava的Localcache类里面已经4872行了,一点都不轻量了。 Ehcache Ehcache更乱,首先它的内存存储中只有惰性检查,没有主动检查过期的,只会在内存超限时不断用近似LRU算法(见上)把内存中的元素刷到磁盘中,在文件存储中才有超时检查的线程,FAQ里专门解释了原因。 然后磁盘存储那有一条8小时左右跑一次的线程,每次遍历所有元素…..见DiskStorageFactory里的DiskExpiryTask。 一圈看下来,Ehcache的实现最弱。 文章持续修改,转载时请保留原链接: http://calvin1978.blogcn.com/articles/lru.html

2015-06-28 · 1 min · 56 words · -

Red-Black Tree,红黑树, R-B Tree

Red-Black Tree, 红黑树, R-B Tree https://github.com/julycoding/The-Art-Of-Programming-By-July/blob/master/ebook/zh/03.01.md 二叉查找树 由于红黑树本质上就是一棵二叉查找树,所以在了解红黑树之前,咱们先来看下二叉查找树。 二叉查找树 (Binary Search Tree) ,也称有序二叉树 (ordered binary tree) ,排序二叉树 (sorted binary tree) ,是指一棵空树或者具有下列性质的二叉树: 若任意结点的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若任意结点的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 任意结点的左、右子树也分别为二叉查找树。 没有键值相等的结点 (no duplicate nodes) 。 因为,一棵由n个结点,随机构造的二叉查找树的高度为lgn,所以顺理成章,一般操作的执行时间为O (lgn) . (至于n个结点的二叉树高度为lgn的证明,可参考算法导论 第12章 二叉查找树 第12.4节) 。 但二叉树若退化成了一棵具有n个结点的线性链后,则此些操作最坏情况运行时间为O (n) 。后面我们会看到一种基于二叉查找树-红黑树,它通过一些性质使得树相对平衡,使得最终查找、插入、删除的时间复杂度最坏情况下依然为O (lgn) 。 红黑树 前面我们已经说过,红黑树,本质上来说就是一棵二叉查找树,但它在二叉查找树的基础上增加了着色和相关的性质使得红黑树相对平衡,从而保证了红黑树的查找、插入、删除的时间复杂度最坏为O(log n)。 但它是如何保证一棵n个结点的红黑树的高度始终保持在h = logn的呢?这就引出了红黑树的5条性质: 每个结点要么是红的,要么是黑的。 根结点是黑的。 每个叶结点 (叶结点即指树尾端NIL指针或NULL结点) 是黑的。 如果一个结点是红的,那么它的俩个儿子都是黑的。 对于任一结点而言,其到叶结点树尾端NIL指针的每一条路径都包含相同数目的黑结点。 正是红黑树的这5条性质,使得一棵n个结点是红黑树始终保持了logn的高度,从而也就解释了上面我们所说的"红黑树的查找、插入、删除的时间复杂度最坏为O(log n)“这一结论的原因。 红黑树是不符合AVL树的平衡条件的,即每个节点的左子树和右子树的高度最多差1的二叉查找树。但是提出了为节点增加颜色,红黑是用非严格的平衡来换取增删节点时候旋转次数的降低,任何不平衡都会在三次旋转之内解决,而AVL是严格平衡树,因此在增加或者删除节点的时候,根据不同情况,旋转的次数比红黑树要多。所以红黑树的插入效率更高!!! 这里引用一下知乎上的回答: Answer 1: 如果插入一个node引起了树的不平衡,AVL和RB-Tree都是最多只需要2次旋转操作,即两者都是O(1);但是在删除node引起树的不平衡时,最坏情况下,AVL需要维护从被删node到root这条路径上所有node的平衡性,因此需要旋转的量级O(logN),而RB-Tree最多只需3次旋转,只需要O(1)的复杂度。 其次,AVL的结构相较RB-Tree来说更为平衡,在插入和删除node更容易引起Tree的unbalance,因此在大量数据需要插入或者删除时,AVL需要rebalance的频率会更高。因此,RB-Tree在需要大量插入和删除node的场景下,效率更高。自然,由于AVL高度平衡,因此AVL的search效率更高。 map的实现只是折衷了两者在search、insert以及delete下的效率。总体来说,RB-tree的统计性能是高于AVL的。 作者: Acjx 链接: http://www.zhihu.com/question/20545708/answer/58717264 Answer 2 这个总结比较好: 红黑树的 查询性能略微逊色于AVL树,因为他比avl树会稍微不平衡最多一层,也就是说红黑树的查询性能只比相同内容的avl树最多多一次比较,但是,红黑树在插入和删除上完爆avl树, avl树每次插入删除会进行大量的平衡度计算,而红黑树为了维持红黑性质所做的红黑变换和旋转的开销,相较于avl树为了维持平衡的 开销要小得多 ...

2015-06-28 · 1 min · 148 words · -

Iterator, Enumeration

Iterator, Enumeration http://www.cnblogs.com/skywang12345/p/3311275.html Iterator和Enumeration区别 在Java集合中,我们通常都通过 “Iterator(迭代器)” 或 “Enumeration(枚举类)” 去遍历集合。今天,我们就一起学习一下它们之间到底有什么区别。 我们先看看 Enumeration.java 和 Iterator.java的源码,再说它们的区别。 Enumeration是一个接口,它的源码如下: package java.util; public interface Enumeration { boolean hasMoreElements(); E nextElement(); } Iterator也是一个接口,它的源码如下: package java.util; public interface Iterator { boolean hasNext(); E next(); void remove(); } 看完代码了,我们再来说说它们之间的区别。 (01) 函数接口不同 Enumeration只有2个函数接口。通过Enumeration,我们只能读取集合的数据,而不能对数据进行修改。 Iterator只有3个函数接口。Iterator除了能读取集合的数据之外,也能数据进行删除操作。 (02) Iterator支持fail-fast机制,而Enumeration不支持。 Enumeration 是JDK 1.0添加的接口。使用到它的函数包括Vector、Hashtable等类,这些类都是JDK 1.0中加入的,Enumeration存在的目的就是为它们提供遍历接口。Enumeration本身并没有支持同步,而在Vector、Hashtable实现Enumeration时,添加了同步。 而Iterator 是JDK 1.2才添加的接口,它也是为了HashMap、ArrayList等集合提供遍历接口。Iterator是支持fail-fast机制的: 当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast事件。 第2部分 Iterator和Enumeration实例 下面,我们编写一个Hashtable,然后分别通过 Iterator 和 Enumeration 去遍历它,比较它们的效率。代码如下: 按 Ctrl+C 复制代码 按 Ctrl+C 复制代码 ...

2015-06-27 · 1 min · 77 words · -

ReferenceQueue

ReferenceQueue 引用队列 ReferenceQueue 使用 SoftReference,WeakReference,PhantomReference 的时候,可以关联一个 ReferenceQueue。那么当垃圾回收器准备回收一个被引用包装的对象时,该引用会被加入到关联的 ReferenceQueue。程序可以通过判断引用队列中是否已经加入引用, 来了解被引用的对象是否被GC回收。 作者: leilifengxingmw 链接: https://www.jianshu.com/p/6ae4f53a4752 来源: 简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 http://www.iflym.com/index.php/java-programe/201407140001.html 在java的引用体系中,存在着强引用,软引用,虚引用,幽灵引用,这4种引用类型。在正常的使用过程中,我们定义的类型都是强引用的,这种引用类型在回收中,只有当其它对象没有对这个对象的引用时,才会被GC回收掉。简单来说,对于以下定义: Object obj = new Object(); Ref ref = new Ref(obj); 在这种情况下,如果 ref 没有被 GC,那么 obj 这个对象肯定不会 GC 的。因为 ref 引用到了 obj。如果 obj 是一个大对象呢,多个这种对象的话,应用肯定一会就挂掉了。 那么,如果我们希望在这个体系中,如果obj没有被其它对象引用,只是在这个Ref中存在引用时,就把obj对象gc掉。这时候就可以使用这里提到的Reference对象了。 我们希望当一个对象被gc掉的时候通知用户线程,进行额外的处理时,就需要使用引用队列了。ReferenceQueue即这样的一个对象,当一个obj被gc掉之后,其相应的包装类,即ref对象会被放入queue中。我们可以从queue中获取到相应的对象信息,同时进行额外的处理。比如反向操作,数据清理等。 2 使用队列进行数据监控 一个简单的例子,通过往map中放入10000个对象,每个对象大小为1M字节数组。使用引用队列监控被放入的key的回收情况。代码如下所示: Object value = new Object(); Map<Object, Object> map = new HashMap<>(); for(int i = 0;i < 10000;i++) { byte[] bytes = new byte[_1M]; WeakReference<byte[]> weakReference = new WeakReference<byte[]>(bytes, referenceQueue); map.put(weakReference, value); } System.out.println("map.size->" + map.size()); 这里使用了weakReference对象,即当值不再被引用时,相应的数据被回收。另外使用一个线程不断地从队列中获取被gc的数据,代码如下: ...

2015-06-26 · 2 min · 262 words · -

CountDownLatch

CountDownLatch CountDownLatch是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。 CountDownLatch和CyclicBarrier的区别 (01) CountDownLatch的作用是允许1或N个线程等待其他线程完成执行;而CyclicBarrier则是允许N个线程相互等待。 (02) CountDownLatch的计数器无法被重置;CyclicBarrier的计数器可以被重置后使用,因此它被称为是循环的barrier。 下面通过CountDownLatch实现: “主线程"等待"5个子线程"全部都完成"指定的工作(休眠1000ms)“之后,再继续运行。 import java.util.concurrent.CountDownLatch; import java.util.concurrent.CyclicBarrier; public class CountDownLatchTest1 { private static int LATCH_SIZE = 5; private static CountDownLatch doneSignal; public static void main(String[] args) { try { doneSignal = new CountDownLatch(LATCH_SIZE); // 新建5个任务 for(int i=0; i<LATCH_SIZE; i++) new InnerThread().start(); System.out.println("main await begin."); // "主线程"等待线程池中5个任务的完成 doneSignal.await(); System.out.println("main await finished."); } catch (InterruptedException e) { e.printStackTrace(); } } static class InnerThread extends Thread{ public void run() { try { Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + " sleep 1000ms."); // 将CountDownLatch的数值减1 doneSignal.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } } } } 主线程通过doneSignal.await()等待其它线程将doneSignal递减至0。其它的5个InnerThread线程,每一个都通过doneSignal.countDown()将doneSignal的值减1;当doneSignal为0时,main被唤醒后继续执行。 ...

2015-06-26 · 1 min · 97 words · -

JAVA的可变类与不可变类

JAVA的可变类与不可变类 可变类和不变类(Mutable and immutable class)的初步定义: 可变类: 当你获得这个类的一个实例引用时,你可以改变这个实例的内容。 不变类: 当你获得这个类的一个实例引用时,你不可以改变这个实例的内容。不可变类的实例一但创建,其内在成员变量的值就不能被修改。 如何创建一个自己的不可变类: .所有成员都是private .不提供对成员的改变方法,例如: setXXXX .确保所有的方法不会被重载。手段有两种: 使用final Class(强不可变类),或者将所有类方法加上final(弱不可变类)。 .如果某一个类成员不是原始变量(primitive)或者不可变类,必须通过在成员初始化(in)或者get方法(out)时通过深度clone方法,来确保类的不可变。 一个示例 import java.util.Date; public final class BrokenPerson { private String firstName; private String lastName; private Date dob; public BrokenPerson( String firstName, public BetterPerson( String firstName, String lastName, Date dob) String lastName, Date dob) { { this.firstName = firstName; this.firstName = firstName; this.lastName = lastName; this.lastName = lastName; this.dob = dob; //error this.dob = new Date( dob.getTime() ); //correct ...

2015-06-26 · 2 min · 359 words · -

archlinux install

archlinux install download iso https://mirrors.tuna.tsinghua.edu.cn/archlinux/iso/ curl -O https://mirrors.tuna.tsinghua.edu.cn/archlinux/iso/2025.10.01/archlinux-2025.10.01-x86_64.iso Ventoy, usb-stick yay -S ventoy-bin copy to ventoy usb partition 用 ventoy U 盘引导系统 启动 sshd 设置 root 密码 进入 root@archiso 之后先设置 root 密码 passwd 连无线网 # 20250501, archlinux 的 iso 里默认已经安装 wpa_supplicant # start systemd-networkd and systemd-resolved service systemctl start systemd-networkd systemctl start systemd-resolved.service # wifi network 有默认配置 /etc/systemd/network/wifi.network # 设置 wifi 密码, 注意后面的 wlp3s0 替换成无线网卡的名字, 用 `ip a` 看一下 # psk 里写明文的密码 cat /etc/wpa_supplicant/wpa_supplicant-wlp3s0.conf network={ ssid="w1100n" psk="wifi_password_0" } sudo systemctl start wpa_supplicant@wlp3s0 systemctl start sshd 在 virtual box 里安装得设置一下端口映射 ...

2015-06-25 · 4 min · 655 words · -