HashMap的fast-fail和ConcurrentHashMap的fail-safe实例
通告:个人博客迁往 https://www.cnblogs.com/xsl-thumb-rfcs
Java HashMap遍历过程中如果元素被修改会导致遍历失败,ConcurrentHashMap则不会有这个问题。由此引出HashMap的fast-fail机制和ConcurrentHashMap的的fail-safe机制。
看如下实例。
首先看HashMap的fast-fail
package com;import java.util.HashMap;
import java.util.Map;public class TestHashMapFastFail
{public static void main(String[] args){System.out.println("test HashMap fast-fail");Map<Integer, String> testHashMap = new HashMap<Integer, String>();testHashMap.put(1000, "1000");testHashMap.put(2000, "2000");testHashMap.put(3000, "3000");testHashMap.put(4000, "4000");testHashMap.put(5000, "5000");System.out.println(testHashMap.size());for (Map.Entry<Integer, String> entry : testHashMap.entrySet()){int key = entry.getKey();System.out.println("key=" + key);if (key == 3000){testHashMap.remove(key);}}System.out.println(testHashMap.size());for (Map.Entry<Integer, String> entry : testHashMap.entrySet()){System.out.println(entry.getKey() + "-->" + entry.getValue());}}
}
运行结果
test HashMap
5
key=2000
key=4000
key=1000
key=3000
Exception in thread "main" java.util.ConcurrentModificationExceptionat java.util.HashMap$HashIterator.nextNode(HashMap.java:1437)at java.util.HashMap$EntryIterator.next(HashMap.java:1471)at java.util.HashMap$EntryIterator.next(HashMap.java:1469)at com.TestHashMapFastFail.main(TestHashMapFastFail.java:18)
可以看到执行remove操作后,下一轮迭代立刻失效,并抛出异常,这就是所谓的fast-fail。
再看ConcurrentHashMap的fail-safe
package com;import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;public class TestConcurrentHashMapFailSafe
{public static void main(String[] args){System.out.println("test ConcurrentHashMap fast-fail");Map<Integer, String> testConcurrentHashMap = new ConcurrentHashMap<Integer, String>();testConcurrentHashMap.put(100, "100");testConcurrentHashMap.put(200, "200");testConcurrentHashMap.put(300, "300");testConcurrentHashMap.put(400, "400");testConcurrentHashMap.put(500, "500");System.out.println(testConcurrentHashMap.size());for (Map.Entry<Integer, String> entry : testConcurrentHashMap.entrySet()){int key = entry.getKey();System.out.println("key=" + key);if (key == 300){testConcurrentHashMap.remove(key);}}System.out.println(testConcurrentHashMap.size());for (Map.Entry<Integer, String> entry : testConcurrentHashMap.entrySet()){System.out.println(entry.getKey() + "-->" + entry.getValue());}}
}
运行结果
test ConcurrentHashMap fast-fail
5
key=400
key=100
key=500
key=200
key=300
3
100-->100
500-->500
300-->300
可以看出,尽管在迭代过程中执行了remove操作,但是ConcurrentHashMap对外的表现仍然正常,这就是所谓的fail-safe。原因在于ConcurrentHashMap返回的迭代器是弱一致性,ConcurrentHashMap底层数据结构改变时并且不会抛出ConcurrentModificationException异常。
所以,这也是选择ConcurrentHashMap可以获得的一个额外好处,或者说是解决HashMap fast-fail的一种方法,还有一个方法就是使用迭代器的remove方法而不是使用集合的remove方法,示例如下。
package com;import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;public class TestHashMapFastFail2
{public static void main(String[] args){System.out.println("test solve HashMap fast-fail");Map<Integer, String> testHashMap = new HashMap<Integer, String>();testHashMap.put(1000, "1000");testHashMap.put(2000, "2000");testHashMap.put(3000, "3000");testHashMap.put(4000, "4000");testHashMap.put(5000, "5000");System.out.println(testHashMap.size());Iterator iterator = testHashMap.entrySet().iterator();while (iterator.hasNext()){int key = (int)((Map.Entry)iterator.next()).getKey();System.out.println("key=" + key);if (key == 2000 || key == 4000){iterator.remove();}}System.out.println(testHashMap.size());for (Map.Entry<Integer, String> entry : testHashMap.entrySet()){System.out.println(entry.getKey() + "-->" + entry.getValue());}}
}
运行结果
test solve HashMap fast-fail
5
key=2000
key=4000
key=1000
key=3000
key=5000
3
1000-->1000
3000-->3000
5000-->5000
集合的 fast-fail 问题是初学者很容易犯的错误。
说说fast-fail机制和fail-safe机制设计的原因。有人可能会问,既然fast-fail有这么多弊端,为什么还要设计呢,以HashMap为例,因为HashMap本身就是设计成线程不安全的,不支持多个线程同时安全修改,但这也意味着HashMap有较快的速度。fail-safe机制设计的初衷就是保证多线程并发安全地修改集合或Map类。当然,本文的用例都是单线程中的修改操作,主要是为了引出这2个概念。
HashMap的fast-fail和ConcurrentHashMap的fail-safe实例相关推荐
- 非线程安全的HashMap 和 线程安全的ConcurrentHashMap
在平时开发中,我们经常采用HashMap来作为本地缓存的一种实现方式,将一些如系统变量等数据量比较少的参数保存在HashMap中,并将其作为单例类的一个属性.在系统运行中,使用到这些缓存数据,都可以直 ...
- P5357 【模板】AC自动机(二次加强版)(AC自动机建fail树dfs求模式串出现次数)
P5357 [模板]AC自动机(二次加强版)(AC自动机建fail树dfs求模式串出现次数) 传送门 形式上,AC 自动机基于由若干模式串构成的 Trie 树,并在此之上增加了一些 fail 边:本质 ...
- Java7/8 中的 HashMap 和 ConcurrentHashMap
Java7 HashMap 数组+链表 Java7 ConcurrentHashMap Segment数组+HashEntry数组链表+ReenTrantLock分段锁 Java8 HashMa ...
- BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MB Submit: 2545 Solved: 1419 [Submit][S ...
- 【BZOJ4231】回忆树 离线+fail树+KMP
[BZOJ4231]回忆树 Description 回忆树是树. 具体来说,是n个点n-1条边的无向连通图,点标号为1~n,每条边上有一个字符(出于简化目的,我们认为只有小写字母). 对一棵回忆树来说 ...
- ConcurrentHashMap,一个更快的HashMap
ConcurrentHashMap 是 Doug Lea 的 util.concurrent 包的一部分,它提供比 Hashtable 或者 synchronizedMap 更高程度的并发性.而且,对 ...
- HashMap和ConcurrentHashMap的区别,HashMap的底层源码。
Hashmap本质是数组加链表.根据key取得hash值,然后计算出数组下标,如果多个key对应到同一个下标,就用链表串起来,新插入的在前面. ConcurrentHashMap:在hashMap的基 ...
- 【重难点】【Java集合 01】HashMap 和 ConcurrentHashMap
[重难点][Java集合 01]HashMap 文章目录 [重难点][Java集合 01]HashMap 一.HashMap 1.概述 2.JDK 1.8 中的变化 3.链表转换为红黑树 4.扩容问题 ...
- HashMap及ConcurrentHashMap基本原理概述
0.前言 本博文部分文字及图片参考自以下三篇文章,其余内容为本人经过思考及总结后所写,仅作为学习分享使用,如有侵权,请联系本人删除,谢谢. 1.什么是HashMap 2.高并发下的HashMap 3. ...
- HashMap——ConcurrentHashMap
HashMap--ConcurrentHashMap 姚博文 文章出处:飞诺网(www.firnow.com):http://dev.firnow.com/course/3_program/java/ ...
最新文章
- 综述:目标检测二十年
- matlab p-tite分割图像,P'tite fourmi
- 廖雪峰python2.7教程_Python 2.7教程
- C语言计数排序Counting sort 算法(附完整源码)
- javascript获取url参数的代码
- 21 个非常有用的 .htaccess 提示和技巧
- [webpack3.8.1]Guides-4-Output Management(输出管理)
- 斯坦福计算机录取难吗,申请斯坦福究竟有多难? 什么样条件的人才能被斯坦福录取?斯坦福大学直播!...
- flink 1.9.0 编译:flink-shaded-hadoop-2 找不到
- android面试经典,Android经典面试题集锦(一)
- JAVA排序:快速排序算法
- php adodb 统计,php之adodb简介
- ArcGIS遇到严重的应用程序错误的解决办法
- 如何改变计算机内存配置文件,电脑内存使用率过高怎么解决?教你如何调整内存大小...
- 苹果照片未删却不见了_手机删除的照片如何恢复?不得不说这方法好!
- linux 原型软件,7款免费原型设计工具,总有一款是你的菜!
- 电机控制器功率电路MOS管及驱动芯片选型若干问题总结
- 功能性测试用例设计方法深入理解
- 微信开放平台-第三方平台-全网发布接入【java版本】
- 全志A33移植openharmony3.1标准系统之添加产品编译