Java8简单的本地缓存实现

原文链接 译文链接 翻译:踏雁寻花,校对:丁一

这里我将会给大家演示用ConcurrentHashMap类和lambda表达式实现一个本地缓存。因为Map有一个新的方法,在key为Null的时候自动计算一个新的value值。非常适合实现cache。来看下代码:

当然,这种方式很傻瓜。即使对于一个非常小的数,例如fibonacci(5),上面的代码也会打印出很多行,而且都是在进行重复计算,输出如下(只截取一部分):

阅读全文

Tomcat进程意外退出的问题分析

感谢同事宏江投递本稿。

节前某个部门的测试环境反馈tomcat会意外退出,我们到实际环境排查后发现不是jvm crash,日志里有进程销毁的记录,从pause到destory的整个过程:

org.apache.coyote.AbstractProtocol pause
Pausing ProtocolHandler
org.apache.catalina.core.StandardService stopInternal
Stopping service Catalina
org.apache.coyote.AbstractProtocol stop
Stopping ProtocolHandler
org.apache.coyote.AbstractProtocol destroy
Destroying ProtocolHandler

阅读全文

分享ppt: java7里的fork-join

以前分享的ppt,介绍了java7里的fork-join框架;

从slideshare下载,或从微盘下载

work-stealing在很多框架里都出现过,从两张图能大致看明白:

不正当使用HashMap导致cpu 100%的问题追究

因最近hashmap误用引起的死循环又发生了一些案例,左耳朵浩子写了一篇blog 疫苗:Java HashMap的死循环,看了一下,大家的分析如出一辙。这篇blog也是好几年前写的了,之前在平台技术部的博客上贴过,随着组织结构的调整,那个博客可能不再维护,把这篇文章在这儿也保存一下。

李鹏同学在blog里写了篇关于HashMap死锁模拟的文章: http://blog.csdn.net/madding/archive/2010/08/25/5838477.aspx 做个纠正,那个不是死锁问题,而是死循环。

这个问题,我们以前讨论过。 校长之前的博客和淘宝的毕玄的《分布式Java应用:基础与实践》一书中都提到过 velocity导致cpu 100% 的bug,起因是HashMap的使用不当所致。

阅读全文

深入剖析ConcurrentHashMap(2)

经过之前的铺垫,现在可以进入正题了。
我们关注的操作有:get,put,remove 这3个操作。

对于哈希表,Java中采用链表的方式来解决hash冲突的。
一个HashMap的数据结构看起来类似下图:

实现了同步的HashTable也是这样的结构,它的同步使用锁来保证的,并且所有同步操作使用的是同一个锁对象。这样若有n个线程同时在get时,这n个线程要串行的等待来获取锁。

阅读全文

深入剖析ConcurrentHashMap(1)

原文是09年时写的,在公司的邮件列表发过,同事一粟 和清英 创建的并发编程网 对这方面概念和实战有更好的文章,贴出来仅供参考。pdf格式在:http://www.slideshare.net/hongjiang/concurrent-hashmap 可以获取

ConcurrentHashMap是Java5中新增加的一个线程安全的Map集合,可以用来替代HashTable。对于ConcurrentHashMap是如何提高其效率的,可能大多人只是知道它使用了多个锁代替HashTable中的单个锁,也就是锁分离技术(Lock Stripping)。实际上,ConcurrentHashMap对提高并发方面的优化,还有一些其它的技巧在里面(比如你是否知道在get操作的时候,它是否也使用了锁来保护?)。

我会试图用通俗一点的方法讲解一下 ConcurrentHashMap的实现方式,不过因为水平有限,在整理这篇文档的过程中,发现了更多自己未曾深入思考过的地方,使得我不得不从新调整了自己的讲解方式。我假设受众者大多是对Java存储模型(JMM)认识并不很深的(我本人也是)。如果我们不断的对ConcurrentHashMap中一些实现追问下去,最终还是要归到JMM层面甚至更底层的。这篇文章的关注点主要在同步方面,并不去分析HashMap中的一些数据结构方面的实现。

阅读全文

话说模式匹配(8) 一个抽取器的例子

一个抽取器的例子

目前List的序列模式(sequence pattern)可以支持对前边若干元素的匹配,比如:List(1,2,3,_*),如果想要实现 List(_*, lastEle) 这样的形式,就需要通过自定义一个抽取器来实现了

// 自定义Extractor
object Append {
    // 接受List结构
    def unapply[A] (l: List[A]) = {
        // 返回Tuple2:前边的若干元素和最后一个元素
        Some( (l.init, l.last) )
    }
}

抽取器里的unapply方法,入参对应你想要进行匹配的对象,出参则是解构后的元素。
比如 list match { case Append(x,y) => } 里面的list对应unapply的入参,x,y对应unapply方法的出参。

阅读全文

话说模式匹配(7) 一个构造器模式的例子(by case class)

第一篇讲述构造器模式匹配的时候给出过tree的例子,因为tree的数据结构很适合用构造器模式来解构。这次再看另一个例子。

scala里的List是个典型的很适用模式匹配的结构,它的接口和数据定义非常凝练。现在我们假设需要一个与List结构正好相反的结构MyList。

List由2部分组成,[head, tail],其中的head是元素本身,而tail则是List类型,也就是一种递归结构。
MyList也由2部分组成 [init, last],其中last是元素本身,而init则是MyList类型。(与List正好颠倒)

// 定义抽象类
abstract class MyList[+A]

// 具体子类,数据由两部分组成:init,last
case class Cons[B] (init:MyList[B], last:B) extends MyList[B]

// 元素为空的MyList单例对象,类似 Nil
case object Empty extends MyList[Nothing]

阅读全文

话说模式匹配(6) case类的细节

我们在第二篇文章里曾提到过:

本质上case class是个语法糖,对你的类构造参数增加了getter访问,还有toString, hashCode, equals 等方法; 最重要的是帮你实现了一个伴生对象,这个伴生对象里定义了apply方法和unapply方法。

现在我们来详细的分析一下case class,对一个简单的样本类

case class B()

阅读全文

话说模式匹配(5) for表达式中的模式匹配

在for表达式中

for(x <- collection) { balabala } 

直觉上以为 x 就是个用于迭代每一个元素的局部变量。

我们看一些例子:

scala> for(i <- List(1,2,3) ) {println(i)}

// 看看语法树  
scala> tb.parse("for(i <- List(1,2,3) ) {println(i)}")
res2: tb.u.Tree = List(1, 2, 3).foreach(((i) => println(i)))

阅读全文

JVM Attach机制实现

感谢支付宝同事【寒泉子】的投稿

attach是什么

在讲这个之前,我们先来点大家都知道的东西,当我们感觉线程一直卡在某个地方,想知道卡在哪里,首先想到的是进行线程dump,而常用的命令是jstack <pid>,我们就可以看到如下线程栈了

阅读全文

无锁并不像人们所说的那么好

原文链接译文连接,译者:梁海舰,校对:李任

注意,我将在这篇文章中说一些关于“无锁”和“无等待”算法的坏话。在我们开始之前,让我来问你一个问题:

你之前有过需要无锁算法来解决问题吗?为什么必须使用无锁算法来解决?
阅读全文

并发不是并行,它更好!

原文链接译文链接,译者:雷哥,饶命,校对:李任

现代社会是并行的:多核、网络、云计算、用户负载,并发技术对此有用。

Go语言支持并发,它提供了:并发执行(goroutines),同步和消息(channels)和多路并发控制(select)。
当Go声称是并发时,人们说:“并发很酷!耶,我可以并行运行了!”,但这是个错误的。因为很多人都不了解他们间的差别。“我用四个处理器来做质数筛选,但是更慢了。”

并发(Concurrency):以可独立执行的进程集合的方式编程(进程是出了名的难定义,这里是通常意义上的进程,不是Linux进程)

并行(Parallelism):以可同时执行的(可能相关的)计算指令方式编程。

两者的区别:并发是同时处理(dealing)很多的事情,并行是同时做(doing)很多的事情。不同,但也相关。一个是关于代码结构,一个是关于代码执行。并发为可能的(不是必须的)并行问题提供了一种解决方案。
阅读全文

[Google Guava] 6-字符串处理:分割,连接,填充

原文链接 译文链接 译者:沈义扬,校对:丁一

连接器[Joiner]

用分隔符把字符串序列连接起来也可能会遇上不必要的麻烦。如果字符串序列中含有null,那连接操作会更难。Fluent风格的Joiner让连接字符串更简单。

[code lang=”java”]
Joiner joiner = Joiner.on("; ").skipNulls();
return joiner.join("Harry", null, "Ron", "Hermione");
[/code]

上述代码返回”Harry; Ron; Hermione”。另外,useForNull(String)方法可以给定某个字符串来替换null,而不像skipNulls()方法是直接忽略null。 Joiner也可以用来连接对象类型,在这种情况下,它会把对象的toString()值连接起来。

[code lang=”java”]
Joiner.on(",").join(Arrays.asList(1, 5, 7)); // returns "1,5,7"
[/code]

警告:joiner实例总是不可变的。用来定义joiner目标语义的配置方法总会返回一个新的joiner实例。这使得joiner实例都是线程安全的,你可以将其定义为static final常量。
阅读全文

[Google Guava] 4-函数式编程

原文链接 译文链接 译者:沈义扬,校对:丁一

注意事项

截至JDK7,Java中也只能通过笨拙冗长的匿名类来达到近似函数式编程的效果。预计JDK8中会有所改变,但Guava现在就想给JDK5以上用户提供这类支持。

过度使用Guava函数式编程会导致冗长、混乱、可读性差而且低效的代码。这是迄今为止最容易(也是最经常)被滥用的部分,如果你想通过函数式风格达成一行代码,致使这行代码长到荒唐,Guava团队会泪流满面。

比较如下代码:

[code lang=”java”]
Function<String, Integer> lengthFunction = new Function<String, Integer>() {
public Integer apply(String string) {
return string.length();
}
};
Predicate<String> allCaps = new Predicate<String>() {
public boolean apply(String string) {
return CharMatcher.JAVA_UPPER_CASE.matchesAllOf(string);
}
};
Multiset<Integer> lengths = HashMultiset.create(
 Iterables.transform(Iterables.filter(strings, allCaps), lengthFunction));
[/code]

或FluentIterable的版本

[code lang=”java”]
Multiset<Integer> lengths = HashMultiset.create(
FluentIterable.from(strings)
.filter(new Predicate<String>() {
public boolean apply(String string) {
return CharMatcher.JAVA_UPPER_CASE.matchesAllOf(string);
}
})
.transform(new Function<String, Integer>() {
public Integer apply(String string) {
return string.length();
}
}));
[/code]

还有

[code lang=”java”]
Multiset<Integer> lengths = HashMultiset.create();
for (String string : strings) {
if (CharMatcher.JAVA_UPPER_CASE.matchesAllOf(string)) {
lengths.add(string.length());
}
}
[/code]

即使用了静态导入,甚至把Function和Predicate的声明放到别的文件,第一种代码实现仍然不简洁,可读性差并且效率较低。
阅读全文

return top