CurrentMap总结

简单介绍CurrentHashMap

ConcurrentMap,它是一个接口,是一个能够支持并发访问的java.util.map集合;

ConcurrentHashMap是一个线程安全,并且是一个高效的HashMap。
spring 缓存注解 通过查看源代码发现将数据存在ConcurrentMap中

Map并发原理

  • ConcurrentMap
    • ConcurrentMap,它是一个接口,是一个能够支持并发访问的java.util.map集合;
    • 在原有java.util.map接口基础上又新提供了4种方法,进一步扩展了原有Map的功能:
    •  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);
      }
      
      putIfAbsent:与原有put方法不同的是,putIfAbsent方法中如果插入的key相同,则不替换原有的value值;
      remove:与原有remove方法不同的是,新remove方法中增加了对value的判断,如果要删除的key--value不能与Map中原有的key--value对应上,则不会删除该元素;
      replace(K,V,V):增加了对value值的判断,如果key--oldValue能与Map中原有的key--value对应上,才进行替换操作;
      replace(K,V):与上面的replace不同的是,此replace不会对Map中原有的key--value进行比较,如果key存在则直接替换;
      
    • 其实,对于ConcurrentMap来说,我们更关注Map本身的操作,在并发情况下是如何实现数据安全的。在java.util.concurrent包中,ConcurrentMap的实现类主要以ConcurrentHashMap为主。接下来,我们具体来看下。
  • ConcurrentHashMap
    *ConcurrentHashMap是一个线程安全,并且是一个高效的HashMap。
    但是,如果从线程安全的角度来说,HashTable已经是一个线程安全的HashMap,那推出ConcurrentHashMap的意义又是什么呢?
    说起ConcurrentHashMap,就不得不先提及下HashMap在线程不安全的表现,以及HashTable的效率!
  • HashMap
    • 底层数据结构不一样,1.7是数组+链表,1.8则是数组+链表+红黑树结构(当链表长度大于8,转为红黑树)。
      JDK1.8中resize()方法在表为空时,创建表;在表不为空时,扩容;而JDK1.7中resize()方法负责扩容,inflateTable()负责创建表。
       1.8中没有区分键为null的情况,而1.7版本中对于键为null的情况调用putForNullKey()方法。但是两个版本中如果键为null,那么调用hash()方法得到的都将是0,所以键为null的元素都始终位于哈希表table【0】中。
      当1.8中的桶中元素处于链表的情况,遍历的同时最后如果没有匹配的,直接将节点添加到链表尾部;而1.7在遍历的同时没有添加数据,而是另外调用了addEntry()方法,将节点添加到链表头部。
      1.7中新增节点采用头插法,1.8中新增节点采用尾插法。这也是为什么1.8不容易出现环型链表的原因。
      1.7中是通过更改hashSeed值修改节点的hash值从而达到rehash时的链表分散,而1.8中键的hash值不会改变,rehash时根据(hash&oldCap)==0将链表分散。
       1.8rehash时保证原链表的顺序,而1.7中rehash时有可能改变链表的顺序(头插法导致)。
      在扩容的时候:1.7在插入数据之前扩容,而1.8插入数据成功之后扩容。
  • CurrentHashMap
    • 与HashMap不同的是,ConcurrentHashMap中多了一层数组结构,由Segment和HashEntry两个数组组成。其中Segment起到了加锁同步的作用,而HashEntry则起到了存储K.V键值对的作用。在ConcurrentHashMap中,每一个ConcurrentHashMap都包含了一个Segment数组,在Segment数组中每一个Segment对象则又包含了一个HashEntry数组,而在HashEntry数组中,每一个HashEntry对象保存K-V数据的同时又形成了链表结构,此时与HashMap结构相同。在多线程中,每一个Segment对象守护了一个HashEntry数组,当对ConcurrentHashMap中的元素修改时,在获取到对应的Segment数组角标后,都会对此Segment对象加锁,之后再去操作后面的HashEntry元素,这样每一个Segment对象下,都形成了一个小小的HashMap,在保证数据安全性的同时,又提高了同步的效率。只要不是操作同一个Segment对象的话,就不会出现线程等待的问题!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值