1. Hashtable 和 HashMap

(1)区别,这两个类主要有以下几方面的不同:
Hashtable和HashMap都实现了Map接口,但是Hashtable的实现是基于Dictionary抽象类。
 
在HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。 
当get()方法返回null值时,即可以表示 HashMap中没有该键,也可以表示该键所对应的值为null。
 因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键,而应该用containsKey()方法来判断。
 而在Hashtable中,无论是key还是value都不能为null 。
 
   这两个类最大的不同在于:
(1)Hashtable是线程安全的,它的方法是同步了的,可以直接用在多线程环境中。
(2)而HashMap则不是线程安全的。在多线程环境中,需要手动实现同步机制。

因此,在Collections类中提供了一个方法返回一个同步版本的HashMap用于多线程的环境:
Java代码
public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {   
 return new SynchronizedMap<K,V>(m);   
 }  
该方法返回的是一个SynchronizedMap 的实例。
SynchronizedMap类是定义在Collections中的一个静态内部类。
它实现了Map接口,并对其中的每一个方法实现,通过synchronized 关键字进行了同步控制。
 
2. 潜在的线程安全问题
上面提到Collections为HashMap提供了一个并发版本SynchronizedMap。
这个版本中的方法都进行了同步,但是这并不等于这个类就一定是线程安全的。
在某些时候会出现一些意想不到的结果。
如下面这段代码:
Java代码
// shm是SynchronizedMap的一个实例   
if(shm.containsKey('key')){   
        shm.remove(key);   
}  
 这段代码用于从map中删除一个元素之前判断是否存在这个元素。
 这里的containsKey和reomve方法都是同步的,但是整段代码却不是。
 
 考虑这么一个使用场景:
线程A执行了containsKey方法返回true,准备执行remove操作;
这时另一个线程B开始执行,同样执行了containsKey方法返回true,并接着执行了remove操作;
然后线程A接着执行remove操作时发现此时已经没有这个元素了。
要保证这段代码按我们的意愿工作,一个办法就是对这段代码进行同步控制,但是这么做付出的代价太大。
 
在进行迭代时这个问题更改明显。Map集合共提供了三种方式来分别返回键、值、键值对的集合:
Java代码
Set<K> keySet();   
  
Collection<V> values();   
  
Set<Map.Entry<K,V>> entrySet();

在这三个方法的基础上,我们一般通过如下方式访问Map的元素:
Java代码
Iterator keys = map.keySet().iterator();   
  
while(keys.hasNext()){   
        map.get(keys.next());   
}  
 
在这里,有一个地方需要注意的是:得到的keySet和迭代器都是Map中元素的一个“视图”,而不是“副本” 。
问题也就出现在这里,当一个线程正在迭代Map中的元素时,另一个线程可能正在修改其中的元素。
此时,在迭代元素时就可能会抛出 ConcurrentModificationException异常。

为了解决这个问题通常有两种方法,
(1)一是直接返回元素的副本,而不是视图。这个可以通过
集合类的 toArray() 方法实现,但是创建副本的方式效率比之前有所降低,
特别是在元素很多的情况下;
(2)另一种方法就是在迭代的时候锁住整个集合,这样的话效率就更低了。

3. 更好的选择:ConcurrentHashMap

java5中新增了ConcurrentMap接口和它的一个实现类ConcurrentHashMap。

ConcurrentHashMap提供了和Hashtable以及SynchronizedMap中所不同的锁机制。
Hashtable中采用的锁机制是一次锁住整个hash表,从而同一时刻只能由一个线程对其进行操作;
而ConcurrentHashMap中则是一次锁住一个桶。
ConcurrentHashMap默认将hash表分为16个桶,诸如get,put,remove等常用操作只锁当前需要用到的桶。
这样,原来只能一个线程进入,现在却能同时有16个写线程执行,并发性能的提升是显而易见的。
 
上面说到的16个线程指的是写线程,而读操作大部分时候都不需要用到锁。只有在size等操作时才需要锁住整个hash表。
 
在迭代方面,ConcurrentHashMap使用了一种不同的迭代方式。
在这种迭代方式中,当iterator被创建后集合再发生改变就不再是抛出ConcurrentModificationException,
取而代之的是  在改变时new新的数据从而不影响原有的数据 。
iterator完成后再将头指针替换为新的数据 。
这样iterator线程可以使用原来老的数据。

而写线程也可以并发的完成改变。

转载于:https://www.cnblogs.com/lianghui66/p/3267452.html

HashMap HashTable ConcurrentHashMap相关推荐

  1. HashMap,HashTable,ConcurrentHashMap面试总结!!!

    原文:https://www.cnblogs.com/hexinwei1/p/10000779.html 一.小总结 1.HashMap .HashTable. ConcurrentHashMap H ...

  2. HashMap,Hashtable,ConcurrentHashMap

    目录 一.多线程使用HashMap的一些线程安全问题 ①造成数据新增丢失 ②扩容时候,造成链表成环(jdk1.7版本) 二.Hashtable和HashMap的区别 ①核心方法加锁 ②其他语法上面的略 ...

  3. hashmap,hashTable concurrentHashMap 是否为线程安全,区别,如何实现的

    http://www.cnblogs.com/aspirant/p/6856487.html 转载于:https://www.cnblogs.com/wuMing-dj/p/6868817.html

  4. hashmap hashtable concurrenthashmap区别

    https://www.cnblogs.com/heyonggang/p/9112731.html

  5. Hashtable,HashMap,ConcurrentHashMap都是Map的实现类,它们在处理null值的存储上有细微的区别,下列哪些说法是正确的

    多选 Hashtable,HashMap,ConcurrentHashMap都是Map的实现类,它们在处理null值的存储上有细微的区别,下列哪些说法是正确的:答案在文末 A. Hashtable的K ...

  6. HashMap HashTable和ConcurrentHashMap的区别

    HashMap和Hashtable的区别 HashMap和Hashtable都实现了Map接口,但决定用哪一个之前先要弄清楚它们之间的分别.主要的区别有:线程安全性,同步(synchronizatio ...

  7. 集合之比较接口器+Map家族的HashMap+LinkedHashMap+Hashtable+ConcurrentHashMap

    集合之比较接口器+Map家族的HashMap+LinkedHashMap+Hashtable+ConcurrentHashMap 一.比较器接口 1.内置比较器 – Comparable import ...

  8. hashmap的特性?HashMap底层源码,数据结构?Hashmap和hashtable ConcurrentHashMap区别?

    1.hashmap的特性? 允许空键和空值(但空键只有一个,且放在第一位) 元素是无序的,而且顺序会不定时改变 key 用 Set 存放,所以想做到 key 不允许重复,key 对应的类需要重写 ha ...

  9. 分析HashTable、HashMap、ConcurrentHashMap的结构、初始化及扩容机制

    目录 一.前沿 二.HashTable 三.HashMap Jdk1.7 Jdk1.8 四.ConcurrentHashMap Jdk1.7 Jdk1.8 五.总结 一.前沿 相信很多同学对HashT ...

最新文章

  1. Angular多个页面引入同一个组件报错The Component ‘MyComponentComponent‘ is declared by more than one NgModule怎么办?
  2. 毒霸主程序集成反流氓
  3. DPKG命令与软件安装、APT
  4. windows不能改密码
  5. VTK:相互作用之Game
  6. LiveVideoStackCon 2021上海站 | 参会指南
  7. 关于Fiori MyAccount无法在standalone环境下运行的问题
  8. matlab数字图像处理课程设计报告,数字图像处理课程设计实验报告.doc
  9. 刚开始学习.NET 怎么样能使自己学习的更快点啊?
  10. Python金融数据挖掘 第11章 复习思考题2 (聚类)选取中华人民共和国第六次人口普查的各地区人口数以及男女比例进行K-Means聚类分析。
  11. Linux C 语言 Socket 通信(多对多)多线程实现
  12. CharSequence接口
  13. 【嵌入式系统设计师笔记】——什么是嵌入式?
  14. RHCE(三、四)NTP时间服务器、SSH远程加密登录
  15. 转盘抽奖角度计算 前端
  16. LncRNA与代谢组联合分析
  17. MA Chapter 3 Presenting information(SRCharlotte)
  18. 双卡 一卡通话 卡2丢网 ---注册状态 VOICE_REGISTRATION_STATE
  19. 如何用QGIS 3.22将遥感影像切割成小矩形图片(机器学习数据)
  20. 图灵奖得主(麦卡锡\霍尔)

热门文章

  1. 重读经典:《An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale》
  2. IMX6怎么移植最新Android,[IMX6Q][Android5.1]移植筆記 --- 無法掛載system文件系統
  3. java 命令行 编译 jar文件_用命令行编译java并生成可执行的jar包
  4. android 按钮按下缩放,android捏缩放
  5. linux ip brd不一致_3 个方便的命令行网速度测试工具 | Linux 中国
  6. 软件测试ipad电池,ipad2020电池有问题是真的吗
  7. suse下删除mysql_每日MySQL之005:SUSE linux下卸載MySQL
  8. mysql账号密码忘_mysql用户名密码忘记了解决方法
  9. leetcode543. 二叉树的直径
  10. leetcode172. 阶乘后的零 最快算法