1、HashMap是线程不安全的,多线程下会有数据安全问题。
2、Hashtable是线程安全的,但是会将整张表锁起来,效率低下
3、ConcurrentHashMap也是线程安全的,效率较高。(在JDK7和JDK8中,底层原理不一样)
-
JDK7:
创建对象:
1.创建一个长度为16,加载因子为0.75的大数组(数组长度固定)
2.创建一个长度为2的小数组,把地址值赋给0索引处(其他索引位置的元素都为null)
添加元素:
1.第一次根据哈希值找到需要存入的索引处
如果为null,则创建一个长度为2的小数组
二次哈希,把元素存入对应的索引处
如果不为null,根据二次哈希找到小数组中对应的索引
如果此处没有元素,则直接存入
当小数组存满时,会自动扩容小数组(扩容两倍)
如果此处有元素,则调用equals方法比较元素
如果equals为true,则不存
如果equals为false,则形成哈希桶结构
-
JDk8:
1.如果使用空参构造创建Concurrent HashMap对象,则什么都不用做,在第一次添加元素的时候创建哈希表
2.计算元素的哈希值找到哈希表中对应的索引,并存入索引中
3.如果索引位置为null,则用CAS算法,将元素添加到索引中
4.如果不为null,则利用volatile关键字获得当前位置最新的节点地址,挂在他下面,形成链表结构
(volatile:强制线程每次使用的时候,都会看一下共享区域最新的值)
5.当链表长度大部等于8时,自动转换成红黑树
6.当链表或者红黑树成为锁对象时,会使用悲观锁保证多线程操作集合时数据的安全性