之前在时候看书上都推荐用Collections.synchronizedMap()来保证thread-safety当时就在想为啥不用ConcurrentHashMap;
然后看了下面这篇文章,讲的还是非常清晰的,所以摘抄过来,原文地址http://www.pixelstech.net/article/1394026282-ConcurrentHashMap-vs-Collections-synchronizedMap()

ConcurrentHashMap and Collections.synchronizedMap() both provide thread-safe operations of collections of data. They are used in multithreaded programs to provide both thread safety and performance improvements. In many cases, we can use either of them.

But the realization of thread safety is different for these two implementations. ConcurrentHashMap will create an HashEntry[] array internally to store the elements passed in from a Map, while Collections.synchronizedMap() will return a SynchronizedMap.

The main difference between these two is that ConcurrentHashMap will lock only portion of the data which are being updated while other portion of data can be accessed by other threads. However, Collections.synchronizedMap() will lock all the data while updating, other threads can only access the data when the lock is released. If there are many update operations and relative small amount of read operations, you should choose ConcurrentHashMap.

Also one other difference is that ConcurrentHashMap will not preserve the order of elements in the Map passed in. It is similar to HashMap when storing data. There is no guarantee that the element order is preserved. While Collections.synchronizedMap(0 will preserve the elements order of the Map passed in. For example, if you pass a TreeMap to ConcurrentHashMap, the elements order in the ConcurrentHashMap may not be the same as the order in the TreeMap, but Collections.synchronizedMap() will preserve the order.

Furthermore, ConcurrentHashMap can guarantee that there is no ConcurrentModificationException thrown while one thread is updating the map and another thread is traversing the iterator obtained from the map. However, Collections.synchronizedMap() is not guaranteed on this. If we obtain an Iterator from Collections.synchronizedMap() by calling map.keySet().iterator() and then traverse the iterator, at the same time if another thread is trying to updating the map by calling map.put(K,V), we will get a ConcurrentModificationException.

Map<String,String> map = Collections.synchronizedMap(new TreeMap<String,String>());

map.put("key1","value1");
map.put("key2","value2");
map.put("key3","value3");

Set<Entry<String,String>> entries = map.entrySet();

Iterator<Entry<String,String>> iter = entries.iterator();

while(iter.hasNext()){
    System.out.println(iter.next()); //Will throw ConcurrentModificationException
    map.remove("key2");  
}

Now I am wondering whether there is one object which can preserve the insertion order of elements like Collections.synchronizedMap() and also doesn't throw ConcurrentModificationException like ConcurrentHashMap. Fortunately since 1.6 there is a class called ConcurrentSkipListMap which can fulfill these two requirements, from the documentation, we can find that ConcurrentSkipListMap will not throw ConcurrentModificationException and also it will preserve the insertion order of the Map passed in. The only drawback it may have is its performance.

You can also check the difference between ConcurrentHashMap and Hashtable for more understanding about ConcurrentHashMap.

由于这篇纯英文,所以我稍微简单点解释一下区别
第一点
ConcurrentHashMap 在update 时候锁 各自的bucket, 在 bucket较多时 性能提示较之明显
Collections.synchronizedMap() 是锁整张表,多个update情况下只能wait咯
第二点
ConcurrentHashMap 不保存顺序 就如hashmap一样,但是Collections.synchronizedMap()是保存的,在jdk6 后 并发跳跃表支持保存顺序,但相应的tradeoff some performance(折衷了一些性能),sigh...
第三点
ConcurrentHashMap 没有采取fast-fail 策略(快速失败,例如各种集合框架暗存modcount字段来标记travese时候是否被更新了,更新之后就抛出异常),而是采取类似于CopyOnWriteArrayList的重新生成对象策略,当然这样可能读到旧数据,但是木有办法的咯
Collections.synchronizedMap() 则抛出ConcurrentModificationException异常
木有啦,如有不对,还请指正(^o^)/~

« 偶然注意到的jdk里的排序DualPivotQuicksort git遇到的问题 »