最近发现webapp项目在客户的server运行几个小时后,会出现整个Server运行很慢,CPU高达100%,刚开始一直认为是哪里内存泄露,但一看该应用占用的内存并没有一直增长,也保持在一个合理的状态。
在排查故障的过程中,发现代码中使用public static TreeMap<String, String> treemap = new TreeMap<String, String>();
来记录状态信息,并且发现multi thread put/get访问该对象,就联想到HashMap是非线程安全,是否TreeMap也是呢?上某度一查,结果还真是。
那如何修改呢?Oracle官网http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6423457建议使用ConcurrentHashMap来替换,线程安全,并且查询效率比TreeMap高。但由于项目中需要对该Map按自然顺序或自定义顺序遍历键,刚好需要用到TreeMap的特性--排序,因此可以在方法加syncronized 或者定义如下
public static Map<String,String> treemap = Collections.synchronizedMap(new TreeMap<String,String>());
修改后再在客户server上运行,该问题就解决了。
但这样的做性能实在太差了,可以使用ConcurrentSkipListMap。这是一个支持高并发度的有序哈希表,并且是无锁的,可在多线程环境下替代TreeMap。JDK1.6开始就已经支持ConcurrentSkipListMap。