Hashmap/Hashtable/ConcurentHashmap/synchronizedMap

本文深入解析了Java集合框架中的线程安全特性,对比了Hashtable、HashMap、Collections.synchronizedMap和ConcurrentHashMap的区别,重点讨论了线程安全与性能之间的权衡。通过分析不同集合类在多线程环境下的表现,揭示了如何在确保数据一致性的同时,提高程序的并发性能。

Hashtable提供了一种易于使用的、线程安全的、关联的map功能。 然而,线程安全性是凭代价换来的——Hashtable的所有方法都是同步的。synchronized是针对整张Hash表的,即每次锁住整张表让线程独占,安全的背后是巨大的浪费。

HashMap提供一个不同步的基类和一个同步的包装器Collections.synchronizedMap(对应List和Collections.synchronizedList,更安全使用CopyOnWriteArrayList),解决了线程安全性问题。 通过将基本的功能从线程安全性中分离开来,Collections.synchronizedMap是有条件地线程安全——所有单个的操作都是线程安全的,但是多个操作组成的操作序列却可能导致数据争用,因为在操作序列中控制流取决于前面操作的结果。允许需要同步的用户可以拥有同步,而不需要同步的用户则不必为同步付出代价。

ConcurrentHashMap和Hashtable主要区别就是围绕着锁的粒度以及如何锁。

24223012_utWQ.jpg

左边便是Hashtable的实现方式---锁整个hash表;而右边则是ConcurrentHashMap的实现方式---锁桶(或段)。 ConcurrentHashMap将hash表分为16个桶(默认值),诸如get,put,remove等常用操作只锁当前需要用到的桶。原来只能一个线程进入,现在却能同时16个写线程进入,并发性的提升是显而易见的。并且ConcurrentHashMap的读取并发,因为在读取的大多数时候都没有用到锁定,所以读取操作几乎是完全的并发操作。


参考:

http://blog.sina.com.cn/s/blog_5157093c0100hm3y.html

http://www.blogjava.net/zlsunnan/archive/2006/07/02/56184.html

转载于:https://my.oschina.net/OQKuDOtsbYT2/blog/212075

### 遍历速度 在遍历速度方面,通常情况下LinkedHashMap遍历会比HashMap慢,但当HashMap容量很大而实际数据较少时,其遍历可能比LinkedHashMap慢。因为LinkedHashMap的遍历速度只和实际数据有关,和容量无关,而HashMap的遍历速度和其容量有关[^1]。 ### 结构特点 LinkedHashMapHashMap多了一个链表的结构,它维护的是一个具有双重链表的HashMapHashMap输出时元素是随机的,而LinkedHashMap输出时元素是有顺序的。LinkedHashMap支持两种排序,插入排序和使用排序,最近使用的元素会移至尾部,例如原本顺序为 M1 M2 M3 M4,使用M3后顺序变为 M1 M2 M4 M3 [^2]。 ### 适用场景 如果Map映射比较复杂且要求高效率,最好使用LinkedHashMap,但多线程访问时可能会造成不同步,需要用`Collections.synchronizedMap`来包装实现同步,实现方式一般为`Map<String, String> map = Collections.synchronizedMap(new LinkedHashMap<String, String>());` [^2]。 ### 排序特性 TreeMap可以对键进行排序,如果不指定自定义的`Comparator`,默认按照键的自然顺序排序;若指定自定义的`Comparator`,则按照自定义规则排序。例如不指定时,TreeMap的键值对按键的自然顺序输出,指定自定义`Comparator`后会按自定义规则输出键值对 [^4]。 ### 性能对比 HashTable基于陈旧的`Dictionary`实现,效率比HashMap差很多,其“线程安全”实现机制效率也非常低,现在一般用`ConcurrentHashMap`,HashTable基本已废弃 [^3]。 以下是简单的代码示例展示三种Map的使用: ```java import java.util.*; public class MapExample { public static void main(String[] args) { // HashMap HashMap<String, String> hashMap = new HashMap<>(); hashMap.put("100", "e"); hashMap.put("5", "f"); hashMap.put("6", "d"); hashMap.put("11", "a"); hashMap.put("12", "c"); hashMap.put("13", "b"); System.out.println("HashMap:"); for (Map.Entry<String, String> entry : hashMap.entrySet()) { System.out.println("key:" + entry.getKey() + " value:" + entry.getValue()); } // LinkedHashMap LinkedHashMap<String, String> linkedHashMap = new LinkedHashMap<>(); linkedHashMap.put("11", "a"); linkedHashMap.put("12", "c"); linkedHashMap.put("13", "b"); linkedHashMap.put("6", "d"); linkedHashMap.put("100", "e"); linkedHashMap.put("5", "f"); System.out.println("\nLinkedHashMap:"); for (Map.Entry<String, String> entry : linkedHashMap.entrySet()) { System.out.println("key:" + entry.getKey() + " value:" + entry.getValue()); } // TreeMap TreeMap<String, String> treeMap = new TreeMap<>(); treeMap.put("100", "e"); treeMap.put("5", "f"); treeMap.put("6", "d"); treeMap.put("11", "a"); treeMap.put("12", "c"); treeMap.put("13", "b"); System.out.println("\nTreeMap:"); for (Map.Entry<String, String> entry : treeMap.entrySet()) { System.out.println("key:" + entry.getKey() + " value:" + entry.getValue()); } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值