数学之美-无限状态遇上质因数 (www.sunhaojie.com)
爱因斯坦:“美,本质上终究是简单性;”

为了满足准确性,我们可以为业务数据增加标记状态,用于表示数据已经被处理情况的描述,因为统计项的无限(在一个比较大的范围有限)增加,所以怎么用有限的字段表示无限的状态的标记;并且因为无序性,业务数据的状态不能限定统计项处理的次序。

质因数的定义:质因数在数论里是指能整除给定正整数的质数。除了1以外,两个没有其他共同质因子的正整数称为互质。因为1没有质因子,1与任何正整数(包括1本身)都是互质。正整数的因数分解可将正整数表示为一连串的质因子相乘,质因子如重复可以指数表示。根据算术基本定理,任何正整数皆有独一无二的质因子分解式。

我们可以使用质数作为每个统计项的编码,统计项编码的乘积合数作为业务数据的标记状态。
by @技术头条 2017-03-23 23:54 查看详情
sproto 的一些更新 (blog.codingnow.com)
sproto 是我设计的一个类 google protocol buffers 的东西。

在很多年前,我在我经手的一些项目中使用 google protocol buffers 。用了好几年,经历了几个项目后,我感觉到它其实是为静态编译型语言设计的协议,其实并没有脱离语言的普适性。在动态语言中,大家都不太愿意使用它(json 更为流行)。一个很大的原因是,protobuffers 是基于代码生成工作的,如果你不使用代码生成,那么它自身的 bootstrap 就非常难实现。

因为它的协议本身是用自身描述的,如果你要解析协议,必须先有解析自己的能力。这是个先有鸡还是先有蛋的矛盾。过去很多动态语言的 binding 都逃不掉引入负责的 C++ 库再加上一部分动态代码生成。我对这点很不爽,后来重头实现了 pbc 这个库。虽然它还有一些问题,并且我不再想维护它,这个库加上 lua 的 bind
by @技术头条 2017-03-23 23:53 查看详情
只是Flask-CAS的Demo而已 (xnow.me)
起了个轻松一点的标题,但其实是折腾CAS的心酸史,跨越大半年的时间,终于搞定了Flask-CAS这个模块。这是个悲伤的故事!

从头说起,CAS是central authentication service的缩写,也是一套单点登录协议标准。每个公司内部有很多自研的、商业的或者开源的系统,如果有了CAS,你只需要在某个接入CAS的站点登录,其它站点就可以自动登录了,不需要再单独验证。听起来很爽吧。这里不讲解具体原理,因为通过搜索引擎找到这篇文章的人应该都是和我曾经一样走投无路只想解决问题的人。。。

没错,我们公司里就部署了这么一套cas系统,我们采用了开源的企业级解决方案https://www.apereo.org/projects/cas, 后台采用OpenLDAP做认证,公司大多数系统都愉快的接入了这套cas。

大半年前,我用Flask写了一套web管理系统想接入公司的CAS做认证,使用Flask-CAS,不成功,太忙就放弃了,转而走上了HTTP Basic access authentication + LDAP的邪路。最近又遇到这么个问题,一个要修改状态的服务,为了防止用户伪造身份,所以还是想接入cas做下身份校验。走上了和Flask-CAS死磕的道路。

首先,不知为何,pip只能安装Flask-CAS的1.0.0版本,不信你看 https://pypi.python.org/simple/flask-cas/,但是为啥我又看到了1.0.1的版本,不信你看https://pypi.python.org/pypi/Flask-CAS。我也没太放在心上,反正先搭建起来再看呗。
by @技术头条 2017-03-23 23:53 查看详情
png的故事:获取图片信息和像素内容 (www.alloyteam.com)
前言

现在时富媒体时代,图片的重要性对于数十亿互联网用户来说不言而喻,图片本身就是像素点阵的合集,但是为了如何更快更好的存储图片而诞生了各种各样的图片格式:jpeg、png、gif、webp等,而这次我们要拿来开刀的,就是png。

简介

首先,png是什么鬼?我们来看看wiki上的一句话简介:
Portable Network Graphics (PNG) is a raster graphics file format that supports lossless data compression.

也就是说,png是一种使用无损压缩的图片格式,而大家熟知的另外一种图片格式——jpeg则是采用有损压缩的方式。用通俗易懂的方式来讲,当原图片数据被编码成png格式后,是可以完全还原成原本的图片数据的,而编码成jpeg则会损耗一部分图片数据,这是因为两者的编码方式和定位不同。jpeg着重于人眼的观感,保留更多的亮度信息,去掉一些不影响观感的色度信息,因此是有损耗的压缩。png则保留原始所有的颜色信息,并且支持透明/alpha通道,然后采用无损压缩进行编码。因此对于jpeg来说,通常适合颜色更丰富、可以在人眼识别不了的情况下尽可能去掉冗余颜色数据的图片,比如照片之类的图片;而png适合需要保留原始图片信息、需要支持透明度的图片。
by @技术头条 2017-03-23 23:50 查看详情
现代化的缓存设计方案 (ifeve.com)
缓存是提升性能的通用方法,现在大多数的缓存实现都使用了经典的技术。这篇文章中,我们会发掘 Caffeine 中的现代化的实现方法。Caffeine 是一个开源的 Java 缓存库,它能提供高命中率和出色的并发能力。期望读者们能被这些想法激发,进而将它们应用到任何你喜欢的编程语言中。

驱逐策略

缓存的驱逐策略是为了预测哪些数据在短期内最可能被再次用到,从而提升缓存的命中率。由于简洁的实现、高效的运行时表现,以及在常规的使用场景下有不错的命中率,LRU(Least Recently Used)策略或许是最流行的驱逐策略。但 LRU 通过历史数据来预测未来是局限的,它会认为最后到来的数据是最可能被再次访问的,从而给与它最高的优先级。

现代缓存扩展了对历史数据的使用,结合就近程度(recency)和访问频次(frequency)来更好的预测数据。其中一种保留历史信息的方式是使用 popularity sketch(一种压缩、概率性的数据结构)来从一大堆访问事件中定位频繁的访问者。可以参考 CountMin Sketch 算法,它由计数矩阵和多个哈希方法实现。发生一次读取时,矩阵中每行对应的计数器增加计数,估算频率时,取数据对应是所有行中计数的最小值。这个方法让我们从空间、效率、以及适配矩阵的长宽引起的哈希碰撞的错误率上做权衡。
by @技术头条 2017-03-23 23:48 查看详情
线程亲和性(Thread Affinity) (ifeve.com)
如果你正在开发低延迟的网络应用,那应该对线程亲和性(Thread affinity)有所了解。线程亲和性能够强制使你的应用线程运行在特定的一个或多个cpu上。通过这种方式,可以消除操作系统进行调度过程导致线程迁移所造成的影响。幸运的是,刚好有一个这么一个java库 Java-Thread-Affinity ,并且很容易就可以整合到你的netty应用中。
by @技术头条 2017-03-23 23:47 查看详情
揭秘 Github 上那些开源项目的 star 数 (pingguohe.net)
前段时间团队内开源了两个小项目:vlayout和LazyScrollView,一般我们可以通过它们的 star 数(即被其他人收藏的数量)来了解它们的受欢迎程度。但是一个项目到底集齐多少个 star 才算受欢迎呢?Github 上那些开源项目的 star 分布是怎样的?……只有了解这些才能更好的评估一个项目的流行程度。好在 Github 有开放第三方接口,提供了足够多的有用信息,我稍微整理了一下,感觉有点意思,分享一下。(以下数据统计于2017年3月18日)
by @技术头条 2017-03-23 23:45 查看详情
更多关于Flexbox布局如何工作的 – 用大彩图和GIF动画解释 (www.css88.com)
我们入门了几个基本的 Flexbox 属性:flex-direction,justify-content,align-items和align-self。

这些属性对于创建基本布局非常有用。 但是一旦你开始使用Flexbox构建网页的时候,你需要更深入学习Flexbox 属性,以发挥它的潜力。

现在让我们深入了解 Flexbox 的缩放 – 以及如何利用它来构建漂亮的自适应布局。
by @技术头条 2017-03-22 00:14 查看详情
Flexbox布局是如何工作的 – 用大彩图和GIF动画解释 (www.css88.com)
Flexbox 布局将我们从CSS的邪恶(如垂直对齐)中拯救了出来。

很好,Flexbox 确实实现了这个目标。 但掌握新的弹性模型可能还是具有一点挑战性的。

所以,让我们以动图的形式来看看 Flexbox 的工作原理,这样我们可以使用它来构建更好的布局。

Flexbox 的基本原理是让布局变得灵活和直观。

为了实现这个目标,它让容器自己决定如何均匀分配它的子元素 – 包括子元素的大小和相互之间的间隔。

这听起来是很不错的原则。 但让我们看看它在实践中又会是什么样子的呢。

在本文中,我们将探讨 5 个最常见的 Flexbox 属性。我们将探索他们究竟做什么,如何使用它们,以及它们会产生什么实际效果。
by @技术头条 2017-03-21 23:59 查看详情
利用GDB、KGDB调试应用程序及内核驱动模块 (blog.nsfocus.net)
这几天看了一下linux内核提权的一个漏洞,里面涉及到了驱动程序漏洞及驱动调试内容,由于各类linux操作系统版本的不同,如果不能在自己机器上亲自调试驱动程序,可以说即使给了漏洞利用的POC源码也根本无法成功利用。因为内核漏洞的利用涉及到指令集的POC构造,不同内核版本模块加载指令地址不同,导致即使有POC也根本无法利用,只有在自己系统中亲自调试,才能做出相应的修改,达到内核漏洞利用的效果。这样就要求我们对linux内核驱动的调试过程,调试方法有个深入了解。经过两天的各处查找,配置,调试,终于弄清楚了内核调试的基本方法,为之后内核调试,漏洞分析提供技术支持。
目标

在驱动程序开发或是内核漏洞分析过程中经常需要对内核模块进行调试。在通常情下对于驱动程序的调试是利用最直接的方式即打印调试的方式,在驱动程序中通过printk,加入调试信息。同时通过动态加载模块的方式,即可实现对驱动的动态调试,这也是最简单的调试方式。而对于内核漏洞的分析,由于linux系统是开源项目,所有不管对于应用程序的调试还是对内核驱动程序的调试都可以通过查看源码找到漏洞的触发点。

那如果想像调试用户态应用程序一样对内核驱动做动态的源码即调试或是更进一步的对驱动程序进行汇编级调试或是开发内核漏洞利用程序那又该怎么办呢?也许有人会说一般没有必要进行汇编级调试。但是在对内核漏洞利用过程中经常需要调试内核驱动程序,并且需要对内核驱动进行汇编指令级单步跟踪,这样才能确定程序的走向。或是我们需要构造特殊的指令块来完成某项功能。这样就对我们调试内核带来的新的挑战。

那内核里面又是怎么实现的呢,又该如果能够去跟进内核内部去调试呢?

本文就是要解决这个问题:在动态汇编调试用户态应用程序的同时,能够跟进应用程序的的系统调用接口,直接源码级或是汇编级的调试(如果没有符号表)调试驱动程序。

本文演示的程序是通过一个应用程序demo,调用自己写的一个驱动程序接口,通过在调试应用程序的是时候能够跟进调试驱动程序。搭建这样的环境我们使用了vmware虚拟机,该虚拟机使用普遍,安装简单。为了能够调试程序,需要一个目标机和一个客户机。

目标机是用来安装驱动程序,同时运行应用程序,应用程序会调用驱动程序中的接口。同时目标机自己调试应用程序(用户态使用GDB调试)。

客户机是用来连接客户机,同时在客户机中调试目标机中的驱动程序(使用GDB调试)。

需要注意几点:
为了能够能够调试目标机的驱动程序,要求目标机需要支持KGDB调试。
为了能让客户机与目标机通信,我们在vmware中配置这两台机器通过串口通信调试。
客户机如果要支持驱动的源码级调试需要将驱动程序的符号表加载的客户机的调试器中。
本文用的vmware虚拟机需要将目标机和客户机同时安装在虚拟机中。
由于在文章中会包含客户机和目标机的操作过程和调试过程,本文中会使用绿框表示客户机相关操作,使用红框表示目标机上的相关操作。
by @技术头条 2017-03-14 18:55 查看详情
2017年值得关注的3个JavaScript库 (www.css88.com)
唷,2016结束了! 这一年对于世界和JavaScript领域来说都是疯狂的一年。 无数新的令人印象深刻的库和框架涌现,你可能不需要 JavaScript 展示了一些模式,提出了使用 JavaScript 的一些问题,和一张Nolan Lawson谈前端的幻灯片引起了业内牛人的一些骚动和响应,像 Jeremy Keith 和 Christian Heilmann ,NoLan总把这些讨论结成了一篇文章。我开始认为用”疯狂”用来描述这一年有点儿低调了,2016是发神经了。

这一年也包括JavaScript疲劳。许多开发人员正在经历JavaScript的生态系统疲劳,因为需要大量的工具和配置来设置一个“现代化”的JavaScript项目。关于这一点,许多开发人员分享了他们的想法,更多”JavaScript很累很累”类似的文章出现。

为了帮助你和我能在晚上睡个安稳觉,我整理了一个前端开发列表,包含的3个有前途的通用库/框架。
by @技术头条 2017-03-12 18:12 查看详情
Cgroup – Linux的IO资源隔离 (liwei.life)
跟内存管理那部分复杂度类似,IO的资源隔离要讲清楚也是比较麻烦的。这部分内容都是这样,配置起来简单,但是要理解清楚确没那么简单。这次是跟Linux内核的IO实现有关系。对于IO的速度限制,实现思路跟CPU和内存都不一样。CPU是针对进程占用时间的比例限制,内存是空间限制,而当我们讨论IO资源隔离的时候,实际上有两个资源需要考虑,一个是空间,另一个是速度。对于空间来说,这个很简单,大不了分区就是了。现实手段中,分区、LVM、磁盘配额、目录配额等等,不同的分区管理方式,不同的文件系统都给出了很多不同的解决方案。所以,空间的限制实际上不是cgroup要解决的问题,那就是说,我们在这里要解决的问题是:如何进行IO数据传输的速度限制。

限速这件事情,现实中有很多模型、算法去解决这个问题。比如,如果我们想控制高速公路上的汽车单位时间通过率,就让收费站每隔固定时间周期只允许通过固定个数的车就好了。这是一种非常有效的控制手段--漏斗算法。现实中这种算法可能在特定情况下会造成资源浪费以及用户的体验不好,于是又演化出令牌桶算法。这里我们不去详细分析这些算法,但是我们要知道,对io的限速基本是一个漏斗算法的限速效果。无论如何,这种限速都要有个“收费站”这样的设施来执行限速,那么对于Linux的IO体系来说,这个”收费站”建在哪里呢?
by @技术头条 2017-03-12 00:06 查看详情
史上最简单的Scala for推导教程 (growthprogrammer.com)
Scala 的 for 语法,本质上就是语法糖。并且十分简单,简单到简短的一篇文章,就可以说清楚。

Scala 中的 for 语句,都是帮你转换成类似 foreach、 map、 flatMap、 withFilter、 filter 之类的语法。并且整个转化过程是递归的,容易理解的。

看完下面是几个例子,你就能立马掌握。这几个例子,是结合了 Scala 官方的yield文档 改进过来的。

第一个例子,转换成 foreach

for(x <- c1) {...}
会被scalac翻译成

c1.foreach(x => {...})
注意,没有出现 yield 关键字。

再来一个:

for(x <- c1; y <- c2) {...}
会展开成:

c1.foreach(x => for(y <- c2) {...})
然后 scalac会再针对里面的 for 再进行转换,直到所有的 for 被转换完。

第二个例子,先 flatMap后 map

for(x <- c1) yield {...}
会被 scalac翻译成

c1.map(x => {...})
注意,这里出现了 yield关键字。

再来一个:

for(x <- c1; y <- c2) yield {...}

会展开成:

c1.flatMap(x => for(y <- c2) yield {...})

然后再展开成

c1.flatMap(x => c2.map( y => {...}))

注意这里多了一个 yield 关键字,所以会用 flatMap、 map 而不用 foreach。

并且,前面的都使用 forMap(比如 c1),最后面使用 map(比如 c2)。

好了,有无 yield的区别讲完了,这也是最重要的区别了,剩下的都很简单,而且不管有无 yield,概念都一样。

接着往下。

第三个例子,尝试 withFilter ,不行再 filter

for(x <- c; if cond) yield {...}
会翻译成

c.withFilter(x => cond).map(x => {...})
如果 c 没有 withFilter 方法,就使用 filter 方法:

c.filter(x => cond).map(x => {...})
第四个例子,加入其它值

for(x <- c; y = ...) yield {...}
会变成

c.map(x => (x, ...)).map((x,y) => {...})
结束

好了,scala 的 for 规则就结束了,就是这么简单。你肯定能记住。
by @技术头条 2017-03-12 00:06 查看详情
10 连抽保底的概率模型 (blog.codingnow.com)
网游里有很多抽卡、开箱子之类的赌性玩法,在最开始,游戏设计者实现的时候,仅仅给这些抽取概率简单的设置了一个值。比如抽卡抽出橙卡的概率是 10% ,那么就是说,玩家每次抽一张卡,有 90% 的可能是白卡,10% 的可能是橙卡。

但大 R 玩家是大爷,需要小心伺候。如果感受不好,人跑了就亏大了。概率这个东西靠改进伪随机数发生器是解决不了体验问题的,大爷要是连抽 20 张都出不来橙卡,那是要怒删游戏的。

连抽 20 张 10% 概率橙卡一张都抽不到的机会多不?一张抽不中的概率是 0.9 ,20 张都抽不中的概率是 0.9 ^20 = 12.2% 。这可不算小数字啊。平均 8 个大 R 就会碰到一次,一下子赶跑了 1/8 的金主,这个责任小策划可担当不起。

所以、一般网游都会用各种规则来避免玩家出现连抽不中的尴尬。例如,我忘记是谁发明的 10 连抽规则:如果你购买一个大包连抽 10 次,我在规则上就保证里面一定至少有一张橙卡。实现它应该并不困难,按常规概率生成 10 张的卡包,如果里面没有橙卡,那么我加一张即可。

但如果我想把 10 抽保底的规则惠及日常抽卡的玩家该怎么做呢?

就是说,我希望任何玩家任何时候,接连抽了 10 张卡,我都想保证这 10 张卡里至少有一张橙卡。

首先,要说明的一点:如果你同时想保证橙卡掉落率是 10% ,也就是在极大范围内,比如系统投放了一万张卡片中,其中要有一千张橙卡。那么同时保证每 10 张卡里有至少一张橙卡的话,结果一定是完全不随机的,也就是必须每抽 9 张白卡,必出一张橙卡。

所以、如果即想要随机(出橙卡的概率稳定),又想有 10 张出一张的保底,那么橙卡投放量是一定超过 1/10 的。

我们之前的游戏用了个很粗暴的方案:记录玩家已经连续几次没有抽中,如果连续次数超过 9 ,就必给他一张橙卡。为什么我说这个方案粗暴,因为它其实破坏了抽卡的自然体验。虽然玩家的确更高兴了,但是概率却很不自然。不自然的方案(其实是生硬的打了个补丁)实现起来还容易出错,我们前段时间就因为实现 bug 多发放了很多稀有物品,这个 bug 就不展开说了。

下面来看看,为什么这么做不自然。

假设橙卡的掉率是 10% ,那么你在获得一张橙卡后,再抽下一张橙卡的概率就是 0.1 。下一张是白卡,再下一张是橙卡的概率是 0.9 * 0.1 ,下两张是白卡,第三张是橙卡的概率是 0.9^2 * 0.1 ……

后续有 10 张及 10 张以上的概率总共有多少呢?我算了一下,大约是 35% 左右。

我们把抽到两张橙卡之间会抽取到的白卡张数排成一个数列的话,这个数列的值的范围是 0 到正无穷。是的,非洲酋长可能永远抽不到橙卡。当然这只是理论值。

如果你读过大学,学的是理工科,没有逃课的话,就应该知道,这个数列是大致符合指数分布的。指数分布正是用来表示独立随机事件发生的时间间隔的。

当我们把这个数列中大于 9 的数字都强行改成 9 ,那么 9 的出现频率就陡然跳变,这是极不自然的。(分布不平滑)

从一致分布的随机数,转换为指数分布的随机数非常简单。如果你懒得自己推导,那么可以在爆栈网上找到公式 。

让我们回答前面的问题,如果我希望获得一个大约每 10 张卡里出一张橙卡的随机数列,除了每次 random 一个 [0,10) 的整数,判断证书是不是 0 以外,还有一个方法。那就是每次抽到一个橙卡后,都从一个指数分布的随机数列中取一个值出来,作为接下来会抽取到白卡的张数。按这个张数去发放白卡,等计数器减到 0 ,就发一张橙卡给玩家。这个白卡张数的数值范围是 [0, inf) 。

用 lua 实现的话,大概是这样的:

math.floor(math.log(1-math.random()) * (-rate)) 其中 rate = 10 。

好了,如果我们想加上 10 张保底,又想让间隔大致符合指数分布怎么办?简单:
function erand(rate)
while true do
local p = math.floor(math.log(1-math.random()) * (-rate))
if p < rate then
return p
end
end
end

让产生出来的数字小于 10 的时候重来一次就好了。如果你担心这里死循环(实际并不会),也可以加上循环上限:

function erand(rate)
for i = 1, 100 do -- 100 可以随便写
local p = math.floor(math.log(1-math.random()) * (-rate))
if p < rate then
return p
end
end
return rate-1
end

当然,一旦加上了 10 张保底,单张出橙卡的概率就大大增加了,增加到多少呢?大约是 21%。如果你希望保持 10% 左右的投放率,那么保底张数大约应该设置在 23 张左右。

ps. 今天在公司群里讨论这个问题时,雷先生提了这么一个问题,说是可以用来做数值策划的面试题:

已知橙卡的抽取率是 10% ,抽一次卡是 1 块钱;而 10 连抽的包可以帮你按同样概率连抽 10 次,但如果没有抽到橙卡的话,系统会补偿一张橙卡给你,换掉 10 张白卡中的一张。

假设白色一文不值,只有橙卡值钱。

那么请问:这个 10 连抽的包到底价值多少?
by @技术头条 2017-03-12 00:04 查看详情
分享一个即插即用的私藏缓动动画JS小算法 (www.zhangxinxu.com)
……实际开发的时候,使用的最多的还是最初的那个她,不仅是因为她给我带来了很多美好的回忆,更重要的是这么多年过去了,她一直保持着那份简单,和外面的那些妖艳*货完全不一样。

而这个相伴自己最久,最无法忘怀的、使用最多的她就是本文要分享的私藏的动画小算法……
by @技术头条 2017-03-12 00:02 查看详情
Cgroup – Linux内存资源管理 (liwei.life)
无论从任何角度看,Linux的内存管理都是一坨麻烦的事情,当然我们也可以用一堆、一片、一块、一筐来形容这个事情,但是毫无疑问,用一坨来形容它简直恰当无比。在理解它之前,我甚至不会相信精妙的和恶心可以同时形容同一件事情,是的,在我看来它就是这样的。其实我只是做个铺垫,让大家明白,我们下面要讲的内容,绝不是一个成体系的知识,所以,学习起来也确实很麻烦。甚至,我写这个技术文章之前一度考虑了很久该怎么写?从哪里开始写?思考了半天,还是不能免俗,我们无奈,仍然先从free命令说起:

[root@zorrozou-pc ~]# free
total used free shared buffers cached
Mem: 131904480 6681612 125222868 0 478428 4965180
-/+ buffers/cache: 1238004 130666476
Swap: 2088956 0 2088956

这个命令几乎是每一个使用过Linux的人必会的命令,但越是这样的命令,似乎真正明白的人越少(我是说比例越少)。一般情况下,对此命令的理解可以分这几个阶段:

我擦,内存用了好多,6个多G,可是我什么都没有运行啊?为什么会这样?Linux好占内存。

嗯,根据我专业的眼光看出来,内存才用了1G多点,还有很多剩余内存可用。buffers/cache占用的较多,说明系统中有进程曾经读写过文件,但是不要紧,这部分内存是当空闲来用的。

free显示的是这样,好吧我知道了。神马?你问我这些内存够不够,我当然不知道啦!我特么怎么知道你程序怎么写的?

如果你的认识在第一种阶段,那么请你继续补充关于Linux的buffers/cache的知识。如果你处在第二阶段,好吧,你已经是个老手了,但是需要提醒的是,上帝给你关上一扇门的同时,肯定都会给你放一条狗的。是的,Linux的策略是:内存是用来用的,而不是用来看的。但是,只要是用了,就不是没有成本的。有什么成本,凭你对buffer/cache的理解,应该可以想的出来。一般我比较认同第三种情况,一般光凭一个free命令的显示,是无法判断出任何有价值的信息的,我们需要结合业务的场景以及其他输出综合判断目前遇到的问题。当然也可能这种人给人的第一感觉是他很外行,或者他真的是外行。

无论如何,free命令确实给我门透露了一些有用的信息,比如内存总量,剩余多少,多少用在了buffers/cache上,Swap用了多少,如果你用了其它参数还能看到一些其它内容,这里不做一一列举。那么这里又引申出另一些概念,什么是buffer?什么是cache?什么是swap?
by @技术头条 2017-03-12 00:02 查看详情
聊聊设计模式(3):门面模式 (www.barretlee.com)
Facade,中文译为门面、外观,所以本文要讲的 Facade Pattern 翻译时经常看到有两个名字,门面模式和外观模式。
by @技术头条 2017-03-12 00:01 查看详情
3个经常被问到的 JavaScript 面试题 (www.css88.com)
JavaScript是所有现代浏览器的官方语言。 因此,JavaScript 问题出现在各种开发人员的面试中。

本文不是讲述最新的JavaScript库,日常的开发实践或任何新的 ES6 函数。 相反,在讨论JavaScript时,经常会在面试中出现这3个问题。 我自己被问到过这些问题,我的朋友告诉我他们也被到问过。

当然,你在JavaScript面试前不应该只学习这3个问题 – 这里有很多 方法 可以让你更好地准备即将到来的面试 – 但面试官可能会问到下面是3个问题,来判断你对JavaScript语言的理解和DOM的掌握程度。

让我们开始吧!请注意,我们将在下面的示例中使用原生 JavaScript,因为你的面试官通常想看看你在没有第三方库(比如jQuery)的帮助下,是如何理解 JavaScript 和 DOM 的。
by @技术头条 2017-03-12 00:00 查看详情
【死磕Java并发】—–Java内存模型之总结 (cmsblogs.com)
经过四篇博客阐述,我相信各位对Java内存模型有了最基本认识了,下面LZ就做一个比较简单的总结。

总结

JMM规定了线程的工作内存和主内存的交互关系,以及线程之间的可见性和程序的执行顺序。一方面,要为程序员提供足够强的内存可见性保证;另一方面,对编译器和处理器的限制要尽可能地放松。JMM对程序员屏蔽了CPU以及OS内存的使用问题,能够使程序在不同的CPU和OS内存上都能够达到预期的效果。

Java采用内存共享的模式来实现线程之间的通信。编译器和处理器可以对程序进行重排序优化处理,但是需要遵守一些规则,不能随意重排序。
原子性:一个操作或者多个操作要么全部执行要么全部不执行;
可见性:当多个线程同时访问一个共享变量时,如果其中某个线程更改了该共享变量,其他线程应该可以立刻看到这个改变;
有序性:程序的执行要按照代码的先后顺序执行;

在并发编程模式中,势必会遇到上面三个概念,JMM对原子性并没有提供确切的解决方案,但是JMM解决了可见性和有序性,至于原子性则需要通过锁或者Synchronized来解决了。

如果一个操作A的操作结果需要对操作B可见,那么我们就认为操作A和操作B之间存在happens-before关系,即A happens-before B。

happens-before原则是JMM中非常重要的一个原则,它是判断数据是否存在竞争、线程是否安全的主要依据,依靠这个原则,我们可以解决在并发环境下两个操作之间是否存在冲突的所有问题。JMM规定,两个操作存在happens-before关系并不一定要A操作先于B操作执行,只要A操作的结果对B操作可见即可。

在程序运行过程中,为了执行的效率,编译器和处理器是可以对程序进行一定的重排序,但是他们必须要满足两个条件:1 执行的结果保持不变,2 存在数据依赖的不能重排序。重排序是引起多线程不安全的一个重要因素。

同时顺序一致性是一个比较理想化的参考模型,它为我们提供了强大而又有力的内存可见性保证,他主要有两个特征:1 一个线程中的所有操作必须按照程序的顺序来执行;2 所有线程都只能看到一个单一的操作执行顺序,在顺序一致性模型中,每个操作都必须原则执行且立刻对所有线程可见。
by @技术头条 2017-03-11 23:58 查看详情
图解java String的不变性 (www.javaranger.com)
字符串一旦在内存中创建,就不能改变。我们应该知道字符串的所有方法都不能改变它自己,而是返回一个新的字符串。

如果我们想要一个可变的字符串,我们应该使用StringBuffer 或者 StringBuilder。否则会浪费gc时间,应为每次都会创建新的字符串对象。
by @技术头条 2017-03-11 23:57 查看详情