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线程可以使用原来老的数据。

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

HashMap HashTable ConcurrentHashMap的更多相关文章

  1. [Java集合] 彻底搞懂HashMap,HashTable,ConcurrentHashMap之关联.

    注: 今天看到的一篇讲hashMap,hashTable,concurrentHashMap很透彻的一篇文章, 感谢原作者的分享. 原文地址: http://blog.csdn.net/zhanger ...

  2. 彻底搞懂HashMap,HashTable,ConcurrentHashMap之关联.

    注: 今天看到的一篇讲hashMap,hashTable,concurrentHashMap很透彻的一篇文章, 感谢原作者的分享.  原文地址: http://blog.csdn.net/zhange ...

  3. HashMap,HashTable,concurrentHashMap,LinkedHashMap 区别

    HashMap 不是线程安全的 HashTable,concurrentHashMap 是线程安全 HashTable 底层是所有方法都加有锁(synchronized) 所以操作起来效率会低 con ...

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

    线程安全类 在集合框架中,有些类是线程安全的,这些都是jdk1.1中的出现的.在jdk1.2之后,就出现许许多多非线程安全的类. 下面是这些线程安全的同步的类: vector:就比arraylist多 ...

  5. Java集合——HashMap,HashTable,ConcurrentHashMap区别

    Map:“键值”对映射的抽象接口.该映射不包括重复的键,一个键对应一个值. SortedMap:有序的键值对接口,继承Map接口. NavigableMap:继承SortedMap,具有了针对给定搜索 ...

  6. HashMap/Hashtable/ConcurrentHashMap区别

    HashMap:每个隔间都没锁门,有人想上厕所,管理员指给他一个隔间,里面没人的话正常用,里面有人的话把这个人赶出来然后用. 优点,每个人进来不耽误都能用:缺点,每一个上厕所的人都有被中途赶出来的危险 ...

  7. HhashMap HashTable ConcurrentHashMap

    hashMap hashTable concurrentHashMap hashMap的效率高于hashTable,hashMap是线程不安全的,并发时hashMap put方法容易引起死循环,导致c ...

  8. HashMap HashTable和ConcurrentHashMap的区别

    HashMap和Hashtable都实现了Map接口,其主要的区别有:线程安全性,同步(synchronization),以及效率. HashMap和Hashtable基本上没啥区别,除了HashMa ...

  9. 沉淀再出发:java中的HashMap、ConcurrentHashMap和Hashtable的认识

    沉淀再出发:java中的HashMap.ConcurrentHashMap和Hashtable的认识 一.前言 很多知识在学习或者使用了之后总是会忘记的,但是如果把这些只是背后的原理理解了,并且记忆下 ...

随机推荐

  1. Atitit 我们的devops战略与规划 规范 推荐标准

    Atitit 我们的devops战略与规划 规范 推荐标准 1. Vm容器化1 2. 热部署tomcat+jrebel 或者resin1 3. 增量更新与差异更新1 4. 补丁提取与应用2 为了方便提 ...

  2. Atitit nodejs5 nodejs6  nodejs 7.2.1  新特性attialx总结

    Atitit nodejs5 nodejs6  nodejs 7.2.1  新特性attialx总结 1.1. Node.js 4.0.0 已经发布了 .这是和 io.js 合并之后的首个稳定版本,它 ...

  3. mongodb更新数组中的所有匹配项

    假如集合中有如下数据 { "_id" : ObjectId("4b97e62bf1d8c7152c9ccb74"), "title" : & ...

  4. 【delphi】关键字详解

    absolute {它使得你能够创建一个新变量, 并且该变量的起始地址与另一个变量相同.} var Str: ]; StrLen: Byte absolute Str; {这个声明指定了变量StrLe ...

  5. vue2 如何操作dom

    在vue中可以通过给标签加ref属性,就可以在js中利用ref去引用它,从而操作该dom元素,以下是个例子,可以当做参考 <template> <div> <div id ...

  6. axios 的应用

    vue更新到2.0之后,作者就宣告不再对vue-resource更新,而是推荐的axios,前一段时间用了一下,现在说一下它的基本用法. 首先就是引入axios,如果你使用es6,只需要安装axios ...

  7. ajaxfileupload.js ajax上传文件(含application/json)

    jQuery.extend({ createUploadIframe: function(id, uri) { //create frame var frameId = 'jUploadFrame' ...

  8. 【UE4】VR模式下全屏(去掉两侧的黑边)

    1.下载UE4源码,用Visual Studio打开源码找到指定文件,修改代码后重新编译得到一个新的UE4编辑器 2.将游戏项目在新的UE4中打开,重新编译. 参考: https://caedmom. ...

  9. C语言 · 集合运算

    算法训练 集合运算   时间限制:1.0s   内存限制:512.0MB    问题描述 给出两个整数集合A.B,求出他们的交集.并集以及B在A中的余集. 输入格式 第一行为一个整数n,表示集合A中的 ...

  10. Django: AttributeError: 'str' object has no attribute 'resolve'

    再次重温Django的时候,遇到了这个错误.看了页面上,没啥有用的信息.遂谷歌一下,原来是一个很低级的错误:It's because you forgot to type the word " ...