Java 非线程安全的HashMap如何在多线程中使用
Java 非线程安全的HashMap如何在多线程中使用
HashMap 是非线程安全的。在多线程条件下,容易导致死循环,具体表现为CPU使用率100%。因此多线程环境下保证 HashMap 的线程安全性,主要有如下几种方法:
- 使用 java.util.Hashtable 类,此类是线程安全的。
- 使用 java.util.concurrent.ConcurrentHashMap,此类是线程安全的。
- 使用 java.util.Collections.synchronizedMap() 方法包装 HashMap object,得到线程安全的Map,并在此Map上进行操作。
- 自己在程序的关键代码段加锁,保证多线程安全(不推荐)
接下来分析上面列举的几种方法实现并发安全的 HashMap 的原理:
(一)java.util.Hashtable类:
查看该类的源码
public synchronized V get(Object key) {
…… //具体的实现省略,请参考 jdk实现
} public synchronized V put(K key, V value) {
…… //具体的实现省略,请参考 jdk实现
} public synchronized V remove(Object key) {
…… //具体的实现省略,请参考 jdk实现
}
上面是 Hashtable 类提供的几个主要方法,包括 get(),put(),remove() 等。注意到每个方法本身都是 synchronized 的,不会出现两个线程同时对数据进行操作的情况,因此保证了线程安全性,但是也大大的降低了执行效率。因此是不推荐的。
(二)使用 java.util.concurrent.ConcurrentHashMap 类:
该类是 HashMap 的线程安全版,与 Hashtable 相比, ConcurrentHashMap 不仅保证了访问的线程安全性,而且在效率上有较大的提高。
ConcurrentHashMap的数据结构如下:
可以看出,相对 HashMap 和 Hashtable, ConcurrentHashMap 增加了Segment 层,每个Segment 原理上等同于一个 Hashtable, ConcurrentHashMap 等同于一个 Segment 的数组。下面是 ConcurrentHashMap 的 put 和 get 方法:
final Segment<K,V> segmentFor(int hash) {
return segments[(hash >>> segmentShift) & segmentMask];
} public V put(K key, V value) {
if (value == null)
throw new NullPointerException();
int hash = hash(key.hashCode());
return segmentFor(hash).put(key, hash, value, false);
} public V get(Object key) {
int hash = hash(key.hashCode());
return segmentFor(hash).get(key, hash);
}
向 ConcurrentHashMap 中插入数据(put) 或者 读取数据(get),首先都要将相应的 Key 映射到对应的 Segment,因此不用锁定整个类, 只要对单个的 Segment 操作进行上锁操作就可以了。理论上如果有 n 个 Segment,那么最多可以同时支持 n 个线程的并发访问,从而大大提高了并发访问的效率。
Java 非线程安全的HashMap如何在多线程中使用的更多相关文章
- 非线程安全的HashMap 和 线程安全的ConcurrentHashMap
在平时开发中,我们经常采用HashMap来作为本地缓存的一种实现方式,将一些如系统变量等数据量比较少的参数保存在HashMap中,并将其作为单例类的一个属性.在系统运行中,使用到这些缓存数据,都可以直 ...
- [Java集合] 彻底搞懂HashMap,HashTable,ConcurrentHashMap之关联.
注: 今天看到的一篇讲hashMap,hashTable,concurrentHashMap很透彻的一篇文章, 感谢原作者的分享. 原文地址: http://blog.csdn.net/zhanger ...
- Java并发基础08. 造成HashMap非线程安全的原因
在前面我的一篇总结(6. 线程范围内共享数据)文章中提到,为了数据能在线程范围内使用,我用了 HashMap 来存储不同线程中的数据,key 为当前线程,value 为当前线程中的数据.我取的时候根据 ...
- JAVA中的线程安全与非线程安全
原文:http://blog.csdn.net/xiao__gui/article/details/8934832 ArrayList和Vector有什么区别?HashMap和HashTable有什么 ...
- java 多线程 线程安全及非线程安全的集合对象
一.概念: 线程安全:就是当多线程访问时,采用了加锁的机制:即当一个线程访问该类的某个数据时,会对这个数据进行保护,其他线程不能对其访问,直到该线程读取完之后,其他线程才可以使用.防止出现数据不一致或 ...
- Java多线程之非线程安全
在Java多线程中我会重点总结五个如下的技术点: 1.非线程安全是如何出现的 2.synchronized对象监视器为Objec时的使用 3.synchronized对象监视器为Class时的使用 4 ...
- java中线程安全和非线程安全的集合
线程安全 非线程安全 Collection Vector ArrayList.LinkedList HashSet.TreeSet Map HashTable HashMap.TreeMap 字符串 ...
- Java线程安全和非线程安全
ArrayList是非线程安全的,Vector是线程安全的:HashMap是非线程安全的,HashTable是线程安全的:StringBuilder是非线程安全的,StringBuffer是线程安全的 ...
- 为什么JAVA虚拟机分为线程共享和非线程共享?
大多数 JVM 将内存区域划分为 Method Area(Non-Heap)(方法区) ,Heap(堆) , Program Counter Register(程序计数器) , VM Stack(虚拟 ...
随机推荐
- BST性能分析&改进思路——平衡与等价
极端退化 前面所提到的二叉搜索树,已经为我们对数据集进行高效的静态和动态操作打开了一扇新的大门.正如我们所看到的,BST从策略上可以看作是将之前的向量(动态数组)和链表结构的优势结合起来,不过多少令我 ...
- Hadoop 少量map/reduce任务执行慢问题
最近在做报表统计,跑hadoop任务. 之前也跑过map/reduce但是数据量不大,遇到某些map/reduce执行时间特别长的问题. 执行时间长有几种可能性: 1. 单个map/reduce任务处 ...
- JAVA-----基于POI实现对Excel导入
在日常项目开发中, 数据录入和导出是十分普遍的需求,因此,导入导出也成为了开发中一个经典的功能.数据导出的格式一般是excel或者pdf,而批量导入的信息一般是借助excel来减轻工作量,提高效率. ...
- Android从无知到有知——NO.1
如期而至的软件设计大赛吹响了重生的号角.正如同我们的指导老师所说,这个暑假会影响你近几年的发展,也可能会决定你以后所走的道路. 是的.我身边就有非常好的样例,有些师哥师姐们常常跟我们说.软件大赛不仅使 ...
- Swift开发教程--使用Storyboard进行界面跳转
使用storyboard结合代码来做确实能够给开发带来非常多的便利. 在实践的过程中,我们常常会遇到界面的跳转问题. 通过控件和界面的建立的"连接"就能够了. 假设是navigat ...
- myeclipse配置SVN插件
方法一:link安装 安装subclipse, MyEclipse SVN插件 1.从官网下载最新的site-1.x.x.zip文件,网址是:folderID=2240" target= ...
- springMVC学习总结(四)springmvc处理json数据类型以及fastjson的使用
springMVC学习总结(四)springmvc处理json数据类型以及fastjson的使用 主要内容: 这篇文章主要是总结之前使用springmv接收json的时候遇到的问题,下面通过前台发送a ...
- 自学WPF之XAML(一)概念
此笔记仅为学习过程中的一些总结,若有不妥之处,请指出,以便更正.下面直接进入正题. XAML:是一种设计UI的标签语言,是XML的派生语言,所以很多XML中的概念语法在XAML中均适用.在XAML标签 ...
- 《程序员修炼之道:从小工到专家》【PDF】下载
<程序员修炼之道:从小工到专家>[PDF]下载链接: https://u253469.ctfile.com/fs/253469-231196340 内容简介 <程序员修炼之道> ...
- 【python】input、int、if-else、注释、while、module(random.randint())语法示例
import random luckyNum=random.randint(2,9) i=1 while i<=3: guessNum=input("请你猜猜我的幸运号码:" ...