HashMap HashTable ConcurrentHashMap

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/460850.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux 安装Resin4.0.40

一、Resin简介Resin官网地址&#xff1a;http://caucho.com/ Resin源码包下载地址&#xff1a;http://caucho.com/products/resin/downloadResin是CAUCHO公司的产品&#xff0c;是一个非常流行的支持servlets和jsp的引擎&#xff0c;速度非常快。Resin本身包含了一个支持HTTP/1…

int main(int argc,char* argv[])详解

int main(int argc,char* argv[])也可以写成int main(int argc,char** argv)。 argc表示程序运行时发送给main函数的命令行参数的个数&#xff08;包括可执行程序以及传参&#xff09;。 argv[]是字符指针数组&#xff0c;它的每个元素都是字符指针&#xff0c;指向命令行中每个…

计算机教师研修计划书,教师信息技术个人研修计划书

《教师信息技术个人研修计划书》由会员分享&#xff0c;可在线阅读&#xff0c;更多相关《教师信息技术个人研修计划书(6页珍藏版)》请在人人文库网上搜索。1、教师信息技术个人研修计划书 教师信息技术个人研修计划书 通过专家教授的讲解引领&#xff0c;不断更新自己的教育观…

java php 等,路径 上级路径,上上级路径表示方法

如何表示上级目录 ../表示源文件所在目录的上一级目录&#xff0c;../../表示源文件所在目录的上上级目录&#xff0c;以此类推。 ../表示源文件所在目录的上一级目录&#xff0c;../../表示源文件所在目录的上上级目录&#xff0c;以此类推。 假设info.html路径是&#xff1a;…

Java内存模型FAQ(四)重排序意味着什么?

在很多情况下&#xff0c;访问一个程序变量&#xff08;对象实例字段&#xff0c;类静态字段和数组元素&#xff09;可能会使用不同的顺序执行&#xff0c;而不是程序语义所指定的顺序执行。编译器能够自 由的以优化的名义去改变指令顺序。在特定的环境下&#xff0c;处理器可能…

第二季2:视频缓存池的简介

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 一、视频缓存池的概念 &#xff08;1&#xff09;视频的本质是多帧图片&#xff0c;图片的本质是RGB或rawRGB数据&#xff0c;视频要占用一段连续内存。 &#xff08;2&#xff09;视频的裁剪、缩…

C#中的字符串

1. 值类型与引用类型比较classProgram { staticvoid Main() { int a 9; //给变量a赋值为9 int b a; //将a的副本给变量b b 10; Console.WriteLine(string.Format("a{0},b{1}", a, b)); Person ZS newPerson(); //张三 ZS.Age 99; //张三…

初二计算机辅导记录,信息技术指导老师的讲课笔记十篇(2)

2.教师观念转变多数学生可深入学习新课改模式&#xff0c;积极转变自己的理念&#xff0c;能够在教学上推动角色的转变&#xff0c;成为教师学习的引导者、组织者、合作者。如龙北四小一年级数学老师刘阳让学员观察统计表&#xff0c;提出数学难题&#xff0c;并进行计算&#…

linux nfs配置

这节我们介绍NFS的相关概念&#xff0c;以及如何配置NFS和在客户端中查看NFS。NFS的配置过程很简单。在服务器端中编辑/etc/exports文件&#xff0c;添加如下内容&#xff1a;/home/nfs-share 192.168.1.122 *(rw,sync) 第一项是要共享的目录&#xff0c;后者为共享的配置参…

1080i、1080p、2K、4K是什么意思?

以下内容源于网络资源的学习与整理&#xff0c;如有侵权请告知删除。 一、数字后面的字母含义 “I”指的是“Interlaced scanning”&#xff0c;即隔行扫描&#xff1b;P指的是“progressive scanning”&#xff0c;即逐行扫描。这两个概念是需要电子枪进行扫描的大背头电视的…

昂着头的艺术-伯爵在城堡的日记

原文请看:http://www.douban.com/note/275619382/ 《昂着头的艺术》文/伯爵在城堡&#xff08;原载于《全球商业经典》2013年4月刊&#xff09;2003 年夏天&#xff0c;电视里到处是带着口罩的“面具侠”&#xff0c;连广告都比平常更少了。远在海南出差的老妈半夜两点钟打来一…

河南面试分数怎么计算机,河南省现行教材(小学计算机面试教案).doc

河南省现行教材(小学计算机面试教案)课 题 1、电子报刊设计课 型 新授课1、掌握艺术字、文字分栏、图文混排等的制作方法。2、锻炼学生利用已有素材进行综合设计的能力。3、培养学生保护环境的意识和责任。教学重点掌握艺术字、文字分栏、图文混排等的制作方法。教学难点掌握艺…

Zabbix中文模式:图片下面的字符乱码

2019独角兽企业重金招聘Python工程师标准>>> Zabbix默认字体放在安装目录的fonts下&#xff1a; # ll fonts/ total 21288 -rw-r--r-- 1 www www 21767952 Jun 11 2009 DejaVuSans.ttf 从windows机器上拷贝一个字体替换掉就可以了&#xff0c;如使用"微软雅黑…

计算机常用存储芯片分为内存和什么,计算机类论文范例,与安徽省计算机一级考试宝典相关研究生毕业论文开题报告范文...

计算机类论文范例,与安徽省计算机一级考试宝典相关研究生毕业论文开题报告范文关于计算机及计算机系统及山东自考方面的免费优秀学术论文范文&#xff0c;计算机类论文答辩开场白,关于安徽省计算机一级考试宝典相关论文范例&#xff0c;对写作计算机论文范文课题研究的大学硕士…

2013网易实习生招聘笔试题

选择题&#xff1a; 1、二维数组int a[3][4]&#xff0c;下列能表示a[1][2]的是&#xff1f; A.*(*(a1)2) B.*(a3) C.(&a[0]1)[2] D.(a[0]1) 2、short a[100]&#xff0c;则sizeof(a)的值是&#xff1f; A.2 B.4 C.200 D.400 问答题&#xff1a; 1、解释…

插入排序---希尔插入排序算法(Javascript版)

取一个小于n的整数作为第一个增量&#xff0c;把序列分组。所有距离为增量的倍数的元素放在同一个组中。先在各组内进行直接插入排序&#xff1b;然后&#xff0c;取第二个增量&#xff08;第二个<第一个&#xff09;重复上述的分组和排序&#xff0c;直至所取的增量1&#…

“视频编码”的相关概念

以下内容源于网络资源的整理&#xff0c;如有侵权请告知删除。 1、视频编码是什么意思&#xff1f; 视频编码&#xff0c;就是指通过特定的压缩技术&#xff0c;将某个视频格式的文件转换成另一种视频格式文件。 &#xff08;能否这样理解&#xff0c;视频编码&#xff0c;约…

常量和字段

常量是一个特殊的符号&#xff0c;它有一个从不变化的值。定义常量符号时&#xff0c;它的值必须能在编译时确定。确定之后&#xff0c;编译器将常量的值保存到程序集的元数据中。这意味着只能为编译器认定的基元类型定义常量。在C#中一下类型都是基元类型&#xff0c;可用于定…

简单实用的二级树形菜单hovertree

原创 hovertree是一个仿京东的树形菜单jquery插件&#xff0c;暂时有银色和绿色两种。官方网址&#xff1a;http://keleyi.com/jq/hovertree/欢迎下载使用查看绿色效果&#xff1a;http://keleyi.com/jq/hovertree/hovertreegreen.htm可以设置菜单宽度(width)&#xff0c;还可以…