Java 多线程下的HashTable、HashMap、ConcurrentHashMap

HashMap

特点

(1)HashMap是线程不安全的,意味着多线程下不能使用该方法,可能会导致意想不到的结果。如果我们细细的查看源码,就会发现HashMap方法没有synchronized这样的加锁操作。

(2)初始化容量:HashMap的默认容量是16.把1像左移动4个字节,变成了10000,是2的4次方也就是16。put后才开辟空间。

(3)默认加载因子:0.75f。

(4)底层实现:数组、链表、红黑树。

        Java中的哈希表采用链地址法,当桶中的存储元素(链表)大于8的时候,进行一次判断。当数组的长度大于64的时候,自动转换成红黑树。转化成红黑树的两个必要条件:桶节点的数量大于8、整个数组的长度大于64。

(5)如何扩容:每一次扩容大小是当前容量的2倍。当map键值对数大于等于加载因子*数组长度时,可能发生扩容;或者当某个桶的链表长度大于8,但是数组长度小于64的时候。

(6)允许键值对中键的值为null。

Hashtable

特点

(1)Hashtable的方法中,均只是简单加了synchronized关键字,在多线程下,是线程安全的。

(2)初始化容量:初始化容量为11。

(3)底层实现:数组和链表。

(4)如何扩容:newsize = olesize * 2+1。拷贝过程中需要该线程完成整个扩容过程,涉及大量的元素拷贝,效率比较低。

(5)Hashtable方法,直接使用了一把大锁,如果多个线程访问同一个Hashtable就很容易产生冲突。

(6)不允许键值对中键的值为null。

ConcurrentHashMap

特点

(1)ConcurrentHashMap方法中,针对性加锁,线程安全。

        对于读的操作,没有加锁,而是使用了volatile关键字保证了内存可见性。只对于写的操作加锁,加锁使用synchronized关键字。细化了锁的粒度。锁的时候不是直接锁住整个对象,而是每一个哈希桶,降低了锁的冲突概率。

(2)ConcurrentHashMap更加充分的使用CAS特性,避免了出现重量级锁的情况。

(3)针对扩容的方式进行优化,采用化零为整的策略。使用锁分段技术,把若干个哈希桶分成一个 "段" ,对每个段分别加锁。降低锁竞争的概率。

(4)不允许键值对中键的值为null。

三者区别

(1)HashMap线程不安全,其他的线程安全。

(2)Hashtable使用一把大锁,导致锁冲突概率很高,ConcurrentHashMap的每一个哈希桶使用一把锁,锁冲突的概率小。

(3)ConcurrentHashMap相对于Hashtable使用了其他优化策略,比如使用CAS特性、使用锁分段技术等。

(4)HashMap中,key值允许为null,另外两个不允许。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值