相信大家对于java中的一些基础知识或多或少还是有一些了解的,这些知识对于后续学习更加高深的java知识是起到非常重要的奠基作用的。一起来简单了解一下吧。
首先说一下ConcurrentHashMap的概念:
ConcurrentHashMap的目标是实现支持高并发、高吞吐量的线程安全的HashMap。
在1.8之前:
数据结构:
ConcurrentHashMap是由Segment数组结构和多个HashEntry数组结构组成。Segment是一种可重入锁ReentrantLock,在ConcurrentHashMap里扮演锁的角色,HashEntry则用于存储键值对数据。
一个ConcurrentHashMap里包含一个Segment数组,Segment的结构和HashMap相似,是一种数组和链表结构, 一个Segment里包含一个HashEntry数组,每个HashEntry是一个链表结构的元素, 每个Segment守护者一个HashEntry数组里的元素,当对HashEntry数组的数据进行修改时,必须首先获得它对应的Segment锁。
put和get的时候,都是现根据key.hashCode()算出放到哪个Segment中: ConcurrentHashMap中默认是把segments初始化为长度为16的数组
在1.8后:
变化:
ConcurrentHashMap的JDK8与JDK7版本的并发实现相比,最大的区别在于JDK8的锁粒度更细,理想情况下talbe数组元素的大小就是其支持并发的最大个数
实现:
改进一:取消segments字段,直接采用transient volatile HashEntry
然后说一下,数据结构:
改进二:将原先table数组+单向链表的数据结构,变更为table数组+单向链表+红黑树的结构。对于hash表来说,最核心的能力在于将key hash之后能均匀的分布在数组中。
概念:
JDK1.8的实现已经摒弃了Segment的概念,而是直接用Node数组+链表+红黑树的数据结构来实现,并发控制使用Synchronized和CAS来操作,整个看起来就像是优化过且线程安全的HashMap,虽然在JDK1.8中还能看到Segment的数据结构,但是已经简化了属性,只是为了兼容旧版本。
一些成员:
Node是ConcurrentHashMap存储结构的基本单元,继承于HashMap中的Entry,用于存储数据。就是一个链表,但是只允许对数据进行查找,不允许进行修改通过TreeNode作为存储结构代替Node来转换成黑红树。
TreeBin:
TreeBin就是封装TreeNode的容器,它提供转换黑红树的一些条件和锁的控制。
// 读写锁状态 static final int WRITER = 1; // 获取写锁的状态 static final int WAITER = 2; // 等待写锁的状态 static final int READER = 4; // 增加数据时读锁的状态最后是,构造器
public ConcurrentHashMap(){}初始化其实是一个空实现, 初始化操作并不是在构造函数实现的,而是在put操作中实现。 还提供了其他的构造函数,有指定容量大小或者指定负载因子,跟HashMap一样。
上文中的相关知识就是为大家详细介绍java中ConcurrentHashMap的内容了。具体的描述还是非常详细的,大家可以多看看。想要了解更多java常见问题,敬请关注奇Q工具网。
推荐阅读:
Concurrenthashmap锁的实现原理有哪些?它又有什么实现方法?