HashTable, HashMap, ConcurrentHashMap 之间的区别

首先HashMap是线程不安全的,而HashTable是线程安全的,两者都是基于Map接口实现的,都是有key-value值,但是HashTable的key-value均不能为null,而HashMap的key-value均可为null。一般HashTable不推荐使用,因为它是无脑加锁的,造成效率很低。一般在多线程下推荐使用ConcurrentHashMap。

优化策略:

1.在锁粒度的控制下

HashTable是直接在方法上添加synchronized,相当于是直接对this加锁,this是针对一个对象,也就是相当于针对哈希表对象进行加锁,一个哈希表就只有一个锁,在多线程下,无论这些线程都是怎么操作哈希表都会产生锁冲突,HashTable底层也是一个链表,就类似于给一个对象加了锁,这个对象的每一个元素都是一个链表,无论怎么操作都会造成锁冲突的。效率就大大降低了

ConcurrentHashMap不是只有一把锁了,而是有多把锁,把每一个链表(哈希桶)都增加了锁,也就是当两个线程访问同一个链表的时候才会产生线程冲突,如果不是同一个链表,则就不会造成锁冲突,而在ConcurrentHashMap中会有多个链表,恰好两个线程操作同一个链表的概率大大降低。所以ConcurrentHashMap的效率就会提升(产生了锁冲突是对性能影响是非常大的);

2.且ConcurrentHashMap只是给写操作加了锁,给读操作不加锁

两个线程写:没有锁冲突

两个线程同时修改:才会有锁冲突

一个线程写,一个线程修改:没有锁冲突

那么一个线程读,一个线程修改会不会造成线程的不安全呢?

我们主要担心的是怕读的结果是一个修改了一半的值,但是ConcurrentHashMap在设计能够保证读到的数据要么是之前没有修改的数据,要么是修改过后的数据,不会读到正在修改到了一半的数据的,另外读的操作也使用到了指令重排序volatile

3.利用到了CAS的特性

ConcurrentHashMap的思路为能不加锁,就不加锁,且很多都是使用到了CAS来实现的

4.扩容操作

HashTable的扩容是,当put元素的时候法案现当前的负载因子已经超过了阈值就需要进行扩容操作,扩容操作是直接申请一个更大的数组,然后把之前旧的数组直接搬运到新的数组上,但是当元素个数特别多的时候,扩容操作就会耽误很长的时间。

ConcurrentHashMap在扩容的时候就不一次性的全部搬运,而是一次搬运一点点。在扩容的时候,会建立一个新的大一点的空间,一点点的进行搬运,在扩容的过程中,旧的和新的会同时存在一段时间,每次进行哈希表的操作的时候就会把旧的内存上的元素搬运一部分到新的空间上,一直到最终 全部搬运完成。如果在这个过程中需要查询元素那么直接在旧的和新的里面一起查,删除元素的话,就直接删除也就不需要在搬运了,如果要插入元素就直接在新的空间里插入进去即可,当全部搬运完成过后就释放旧的空间

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值