ConcurrentMap,它是一个接口,是一个可以支持并发访问的java.util.map集合
在原有java.util.map接口基础上又新提供了4种方法,进一步扩展了原有Map的功能java
public interface ConcurrentMap<K, V> extends Map<K, V> { //插入元素 V putIfAbsent(K key, V value); //移除元素 boolean remove(Object key, Object value); //替换元素 boolean replace(K key, V oldValue, V newValue); //替换元素 V replace(K key, V value); }
与原有put方法不一样的是,putIfAbsent方法中若是插入的key相同,则不替换原有的value值;数组
与原有remove方法不一样的是,新remove方法中增长了对value的判断,若是要删除的key--value不能与Map中原有的key--value对应上,则不会删除该元素;安全
增长了对value值的判断,若是key--oldValue能与Map中原有的key--value对应上,才进行替换操做;多线程
与上面的replace不一样的是,此replace不会对Map中原有的key--value进行比较,若是key存在则直接替换返回原来的value值并发
其实,对于ConcurrentMap来讲,咱们更关注Map自己的操做,在并发状况下是如何实现数据安全的。在java.util.concurrent包中,ConcurrentMap的实现类主要以ConcurrentHashMap为主。接下来,咱们具体来看下。this
ConcurrentHashMap是一个线程安全,而且是一个高效的HashMap。固然HashTable已是一个线程安全的map可是效率很低内部实现是在每一个方法加上了synchronized锁线程
因为synchronized锁加在了HashTable的每个方法上,因此这个锁就是HashTable自己--this。那么,可想而知HashTable的效率是如何,安全是保证了,可是效率却损失了。code
不管执行哪一个方法,整个哈希表都会被锁住,只有其中一个线程执行完毕,释放所,下一个线程才会执行。不管你是调用get方法,仍是put方法皆是如此;对象
public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, java.io.Serializable { public synchronized int size() {...} public synchronized boolean isEmpty() {...} public synchronized V get(Object key) {...} public synchronized V put(K key, V value) {...} }
而 ConcurrentHashMap在ConcurrentHashMap中,每个ConcurrentHashMap都包含了一个Segment数组,在Segment数组中每个Segment对象则又包含了一个HashEntry数组,而在HashEntry数组中,每个HashEntry对象保存K-V数据的同时又造成了链表结构,此时与HashMap结构相同。blog
在多线程中,每个Segment对象守护了一个HashEntry数组,当对ConcurrentHashMap中的元素修改时,在获取到对应的Segment数组角标后,都会对此Segment对象加锁,以后再去操做后面的HashEntry元素,这样每个Segment对象下,都造成了一个小小的HashMap,在保证数据安全性的同时,又提升了同步的效率。只要不是操做同一个Segment对象的话,就不会出现线程等待的问题!
参考