Java 集合快速失败异常
快速失败
在JDK中,查看集合有很多关于快速失败的描述:
注意,此实现不是同步的。如果多个线程同时访问一个哈希映射,而其中至少一个线程从结构上修改了该映射,则它必须 保持外部同步。(结构上的修改是指添加或删除一个或多个映射关系的任何操作;仅改变与实例已经包含的键关联的值不是结构上的修改。)这一般通过对自然封装该映射的对象进行同步操作来完成。如果不存在这样的对象,则应该使用 Collections.synchronizedMap 方法来“包装”该映射。最好在创建时完成这一操作,以防止对映射进行意外的非同步访问,如下所示:
Map m =
Collections.synchronizedMap(new HashMap(...));由所有此类的“collection 视图方法”所返回的迭代器都是快速失败 的:在迭代器创建之后,如果从结构上对映射进行修改,除非通过迭代器本身的 remove 方法,其他任何时间任何方式的修改,迭代器都将抛出 ConcurrentModificationException。因此,面对并发的修改,迭代器很快就会完全失败,而不冒在将来不确定的时间发生任意不确定行为的风险。
注意,迭代器的快速失败行为不能得到保证,一般来说,存在非同步的并发修改时,不可能作出任何坚决的保证。快速失败迭代器尽最大努力抛出 ConcurrentModificationException。因此,编写依赖于此异常的程序的做法是错误的,正确做法是:迭代器的快速失败行为应该仅用于检测程序错误。
快速失败:对于非并发集合来说,在其进行迭代时,例如iterator迭代时,iterator是另起一个线程,若有其他线程(如Collection)进行结构修改(修改了增减了集合中的内容),这个迭代会马上感知到,并且立即抛出
ConcurrentModificationException 异常,而不是迭代完成后才告诉你出错了,引起快速失败。若用iterator进行修改则不会出现这个问题,如iterator.move();也就是说涉及到了多个线程间的同步问题
示例代码:
[java] view plain copy
- package CoreJava;
- import java.util.HashMap;
- import java.util.Hashtable;
- import java.util.Iterator;
- import java.util.Map;
- import java.util.Map.Entry;
- import java.util.concurrent.ConcurrentHashMap;
10. public class ConcurrentHashMapTest {
- 11. public static void main(String[] args) {
- 12.
- 13. Hashtable<String, String> table = new Hashtable<String, String>();
- 14. table.put("a", "vb");
- 15. table.put("s", "er");
- 16. table.put("d", "fg");
- 17. table.remove("d");
- 18. Iterator<Entry<String, String>> iterator = table.entrySet().iterator();
- 19.
- 20. while (iterator.hasNext()) {
- 21. System.out.println(iterator.next().getValue());
- 22. iterator.remove();//采用iterator直接进行修改 程序正常
- 23. // table.put("c", "wc");直接从hashtable增删数据就会报错
- 24. // table.remove("d");直接从hashtable增删数据就会报错 hashtable,hashmap等非并发集合 如果在迭代过程中增减了数据,
- 25. }
- 26.
- 27. System.out.println("-----------");
- 28.
- 29. HashMap<String, String> hashmap = new HashMap<String, String>();
- 30. hashmap.put("a", "vb");
- 31. hashmap.put("s", "er");
- 32. hashmap.put("d", "fg");
- 33. Iterator<Entry<String, String>> iterators = hashmap.entrySet()
- 34. .iterator();
- 35.
- 36. while (iterators.hasNext()) {
- 37. System.out.println(iterators.next().getValue());
- 38. iterators.remove();// 正常
- 39. // hashmap.remove("d");//直接从hashtable增删数据就会报错 hashtable,hashmap等非并发集合,如果在迭代过程中增减了数据,会快速失败 (一检测到修改,马上抛异常)
- 40. }
- 41.
- 42. System.out.println("-----------");
- 43.
- 44. ConcurrentHashMap<String, String> map = new ConcurrentHashMap<String, String>();
- 45. map.put("a", "vb");
- 46. map.put("s", "er");
- 47. map.put("d", "fg");
- 48. Iterator<Entry<String, String>> mapiterator = map.entrySet().iterator();
- 49.
- 50. while (mapiterator.hasNext()) {
- 51. System.out.println(mapiterator.next().getValue());
- 52. map.remove("d");// 正常 并发集合不存在快速失败问题
- 53. map.put("c", "wc");// 正常 并发集合不存在快速失败问题
- 54. }
- 55. System.out.println("-----------");
- 56. for (Map.Entry<String, String> entry : map.entrySet()) {
- 57. System.out.println(entry.getValue() + ", " + entry.getKey());
- 58. }
- 59. System.out.println("-----------");
- 60. for (Map.Entry<String, String> entry : table.entrySet()) {
- 61. System.out.println(entry.getValue() + ", " + entry.getKey());
- 62. }
- 63. }
- 64.
- 65. /*
- 66. * final Entry<K,V> nextEntry() { if (modCount != expectedModCount) throw
- 67. * new ConcurrentModificationException(); Entry<K,V> e = next; if (e ==
- 68. * null) throw new NoSuchElementException();
- 69. *
- 70. * if ((next = e.next) == null) { Entry[] t = table; while (index < t.length
- 71. * && (next = t[index++]) == null) ; } current = e; return e; }
- 72. */
- 73.
74. }
快速失败异常:当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常
解决方法:
A:迭代器删除
B:锁抢回来。集合自已删除。(前提:线程同步的集合)
Java 集合快速失败异常的更多相关文章
- Java最重要的21个技术点和知识点之JAVA集合框架、异常类、IO
(三)Java最重要的21个技术点和知识点之JAVA集合框架.异常类.IO 写这篇文章的目的是想总结一下自己这么多年JAVA培训的一些心得体会,主要是和一些java基础知识点相关的,所以也希望能分享 ...
- Java笔记-快速失败and安全失败
参考资料:http://blog.csdn.net/chenssy/article/details/38151189 快速失败 fail-fast 安全失败 fail-safe java.util包下 ...
- Java的快速失败和安全失败
文章转自https://www.cnblogs.com/ygj0930/p/6543350.html 一:快速失败(fail—fast) 在用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的内容进 ...
- 面试题思考:java中快速失败(fail-fast)和安全失败(fail-safe)的区别是什么?
一:快速失败(fail—fast) 在用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的内容进行了修改(增加.删除.修改),则会抛出Concurrent Modification Exceptio ...
- java中快速失败(fail-fast)和安全失败(fail-safe)的区别是什么?
一:快速失败(fail—fast) 在用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的内容进行了修改(增加.删除.修改),则会抛出Concurrent Modification Exceptio ...
- (简单易懂)Java的快速失败(fail-fast)与安全失败,源码分析+详细讲解
之前在程序中遇到快速失败的问题,在网上找解释时发现网上的问题总结都比较片面,故打算自己总结一个,也可以供以后参考. --宇的季节 首先什么是快速失败? 快速失败是为了提示程序员在多线程的情况下不要用线 ...
- java集合并发操作异常解决方法:CopyOnWriteArrayList
一.我们知道ArrayList是线程不安全的,请编写一个不安全的案例并给出解决方案 HashSet与ArrayList一致 HashMap HashSet底层是一个HashMap,存储的值放在Hash ...
- 【原创】快速失败机制&失败安全机制
这是why技术的第29篇原创文章 之前在写<这道Java基础题真的有坑!我求求你,认真思考后再回答.>这篇文章时,我在8.1小节提到了快速失败和失败安全机制. 但是我发现当我搜索" ...
- 一文搞懂所有Java集合面试题
Java集合 刚刚经历过秋招,看了大量的面经,顺便将常见的Java集合常考知识点总结了一下,并根据被问到的频率大致做了一个标注.一颗星表示知识点需要了解,被问到的频率不高,面试时起码能说个差不多.两颗 ...
随机推荐
- ReSharper 配置及用法(一)
ReSharper是一个JetBrains公司出品的著名的代码生成工具,其能帮助Microsoft Visual Studio成为一个更佳的IDE.它包括一系列丰富的能大大增加C#和Visual Ba ...
- uva 107 - The Cat in the Hat
The Cat in the Hat Background (An homage to Theodore Seuss Geisel) The Cat in the Hat is a nasty c ...
- Linux添加Terminal快捷键和文件系统的总结
一:Fedora 怎样设置终端快捷键 百度连接:http://jingyan.baidu.com/article/cb5d61053598ed005d2fe05c.html ubuntu里面不用设置就 ...
- Leap Motion发布新平台,直击下一代移动端VR/AR手部追踪
2013年,动作捕捉技术公司Leap Motion发布了面向PC的体感控制器,不过销量并不乐观.随着2014年虚拟现实技术的再一次兴起,它发布一款用于Oculus Rift的附加设备,从而正式登上VR ...
- maven 仓库地址:
maven 仓库地址: 共有的仓库 http://repo1.maven.org/maven2/http://repository.jboss.com/maven2/ http://repositor ...
- ACM: meixiuxiu学图论-并查集-最小生成树-解题报告
/* 最小生成树,最小环的最大权值按照排序后去构建最小生成树就可以了,注意遇到的第一个根相同的点就记录权值,跳出,生成的环就是最小权值环. */ //AC代码: #include"iostr ...
- xenu工具介绍
Xenu Link Sleuth 也许是你所见过的最小但功能最强大的检查网站死链接的软件了.你可以打开一个本地网页文件来检查它的链接,也可以输入任何网址来检查.它可以分别列出网站 的活链接以及死链接, ...
- 【noiOJ】p1481
1481:Maximum sum 查看 提交 统计 提问 总时间限制: 1000ms 内存限制: 65536kB 描述 Given a set of n integers: A={a1, a2,. ...
- java画图程序_图片用字母画出来
最近在研究怎样将图片用字母在文本编辑工具中“画”出来. 你看了这个可能还不知道我想说什么? 我想直接上图,大家一定就知道了 第一张:小猫 原图:http://www.cnblogs.com/hongt ...
- Oracle函数解析
一:大小写控制函数 lower()函数:(此函数将全部的大写字母都可以变为小写字母) upper()函数:(将输入的字符串变为大写字母) initcap()函数:(将每个字符串的首字母大写) 二:字 ...