总结HashMap, HashTable, ConcurrentHashMap 之间的区别

HashMap, HashTable, ConcurrentHashMap都是使用同一种数据结构(数组+链表);

  • HashMap多线程状态下是不安全的;
  • HashTable和ConcurrentHashMap是在HashMap的基本的数据结构上进行优化,使他们在多线程下是安全的;
  • HashTable是在每一个关键方法都是用synchronized加锁来确保多线程安全,例如插入,读取,对size进行操作都是加上synchronized关键字;
  • ConcurrentHashMap是进一步的优化,只是写操作时对该“桶”加锁,两个线程读取不同的桶是不互斥的,每个桶都有一个锁,并且读取操作不加锁;

HashTable

  • HashMap的key可以为null,HashTable的key不可以为null
  • 对size的操作也是使用synchronized,效率比较低
  • HashTable就是在HashMap的方法的基础上,加上一个synchronized,同步方法,即使多个线程同时调用同一个方法,也只有一个线程的方法能够执行,其他线程挂起等待,保证了线程安全;

  • 还有一个就是扩容,一旦扩容,就由该线程完成一整个扩过程,所有的数据每一次拷贝都要上锁,效率非常低下,虽然保证了线程安全;

ConcurrentHash

  • ConcurrentHashMap的key不能为null,HashMap的key可以为null;
  • 充分使用CAS机制对size进行操作,提高了效率,避免了重量级锁的出现;
  • ConcurrentHashMap就是在HashTable上的进一步优化,保证线程安全的同时提高效率;
  • ConcurrentHashMap的读操作不上锁,即使多个线程同时读取数据也能同时进行;
  • 但是ConcurrentHashMap对写操作上锁,我们都知道HashMap是数组+链表的数据结构,ConcurrentHashMap也是如此的数据结构,虽然ConcurrentHashMap的方法也上锁,但是每一个链表都是使用不同的锁对象,只是把锁加载链表头,所以不同线程能够同时对不同链表(不同桶)写入,但是对于同一个链表(同一个桶)就必须同一个时刻只能有一个线程进行写入操作;
对于扩容进行优化,ConcurrentHashMap使用:化整为零
  • 第一个发现需要扩容的线程,只需要创建数组,然后只需要复制几个数据过去新数组;
  • 后续每一个操作该数组的线程都要参加将数据从旧数组搬到新数组,一次也只是移动几个数组;
  • 对于插入数据操作,查找过程新老数组都要查找,但是只插入到新数据;
  • 直到旧数组的数据全部移动到新数据,就把旧数组删掉;
  • 通过一点点的移动数据,以此来提高扩容效率,同时不对其他线程的操作造成影响;

拓展

ConcurrentHashMap还对数据进行了优化,由原来的数组+链表变成数组+链表/红黑树。但链表的数据个数超过8个,就会把链表变成红黑树,进一步提高效率;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

a添砖Java

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值