快速失败

JDK中,查看集合有很多关于快速失败的描述:

注意,此实现不是同步的。如果多个线程同时访问一个哈希映射,而其中至少一个线程从结构上修改了该映射,则它必须 保持外部同步。(结构上的修改是指添加或删除一个或多个映射关系的任何操作;仅改变与实例已经包含的键关联的值不是结构上的修改。)这一般通过对自然封装该映射的对象进行同步操作来完成。如果不存在这样的对象,则应该使用 Collections.synchronizedMap 方法来“包装”该映射。最好在创建时完成这一操作,以防止对映射进行意外的非同步访问,如下所示:

Map m =
Collections.synchronizedMap(new HashMap(...));由所有此类的“collection 视图方法”所返回的迭代器都是快速失败 的:在迭代器创建之后,如果从结构上对映射进行修改,除非通过迭代器本身的 remove 方法,其他任何时间任何方式的修改,迭代器都将抛出 ConcurrentModificationException。因此,面对并发的修改,迭代器很快就会完全失败,而不冒在将来不确定的时间发生任意不确定行为的风险。

注意,迭代器的快速失败行为不能得到保证,一般来说,存在非同步的并发修改时,不可能作出任何坚决的保证。快速失败迭代器尽最大努力抛出 ConcurrentModificationException。因此,编写依赖于此异常的程序的做法是错误的,正确做法是:迭代器的快速失败行为应该仅用于检测程序错误。

快速失败:对于非并发集合来说,在其进行迭代时,例如iterator迭代时,iterator是另起一个线程,若有其他线程(如Collection)进行结构修改(修改了增减了集合中的内容),这个迭代会马上感知到,并且立即抛出
ConcurrentModificationException
异常,而不是迭代完成后才告诉你出错了,引起快速失败。若用iterator进行修改则不会出现这个问题,如iterator.move();也就是说涉及到了多个线程间的同步问题

示例代码:

[java] view plain copy

  1. package CoreJava;
  2. import java.util.HashMap;
  3. import java.util.Hashtable;
  4. import java.util.Iterator;
  5. import java.util.Map;
  6. import java.util.Map.Entry;
  7. import java.util.concurrent.ConcurrentHashMap;

10. public class ConcurrentHashMapTest {

  1. 11.     public static void main(String[] args) {
  2. 12.
  3. 13.         Hashtable<String, String> table = new Hashtable<String, String>();
  4. 14.         table.put("a", "vb");
  5. 15.         table.put("s", "er");
  6. 16.         table.put("d", "fg");
  7. 17.         table.remove("d");
  8. 18.         Iterator<Entry<String, String>> iterator = table.entrySet().iterator();
  9. 19.
  10. 20.         while (iterator.hasNext()) {
  11. 21.             System.out.println(iterator.next().getValue());
  12. 22.             iterator.remove();//采用iterator直接进行修改 程序正常
  13. 23.             // table.put("c", "wc");直接从hashtable增删数据就会报错
  14. 24.             // table.remove("d");直接从hashtable增删数据就会报错 hashtable,hashmap等非并发集合 如果在迭代过程中增减了数据,
  15. 25.         }
  16. 26.
  17. 27.         System.out.println("-----------");
  18. 28.
  19. 29.         HashMap<String, String> hashmap = new HashMap<String, String>();
  20. 30.         hashmap.put("a", "vb");
  21. 31.         hashmap.put("s", "er");
  22. 32.         hashmap.put("d", "fg");
  23. 33.         Iterator<Entry<String, String>> iterators = hashmap.entrySet()
  24. 34.                 .iterator();
  25. 35.
  26. 36.         while (iterators.hasNext()) {
  27. 37.             System.out.println(iterators.next().getValue());
  28. 38.             iterators.remove();// 正常
  29. 39.             // hashmap.remove("d");//直接从hashtable增删数据就会报错 hashtable,hashmap等非并发集合,如果在迭代过程中增减了数据,会快速失败 (一检测到修改,马上抛异常)
  30. 40.         }
  31. 41.
  32. 42.         System.out.println("-----------");
  33. 43.
  34. 44.         ConcurrentHashMap<String, String> map = new ConcurrentHashMap<String, String>();
  35. 45.         map.put("a", "vb");
  36. 46.         map.put("s", "er");
  37. 47.         map.put("d", "fg");
  38. 48.         Iterator<Entry<String, String>> mapiterator = map.entrySet().iterator();
  39. 49.
  40. 50.         while (mapiterator.hasNext()) {
  41. 51.             System.out.println(mapiterator.next().getValue());
  42. 52.             map.remove("d");// 正常 并发集合不存在快速失败问题
  43. 53.             map.put("c", "wc");// 正常 并发集合不存在快速失败问题
  44. 54.         }
  45. 55.         System.out.println("-----------");
  46. 56.         for (Map.Entry<String, String> entry : map.entrySet()) {
  47. 57.             System.out.println(entry.getValue() + ", " + entry.getKey());
  48. 58.         }
  49. 59.         System.out.println("-----------");
  50. 60.         for (Map.Entry<String, String> entry : table.entrySet()) {
  51. 61.             System.out.println(entry.getValue() + ", " + entry.getKey());
  52. 62.         }
  53. 63.     }
  54. 64.
  55. 65.     /*
  56. 66.      * final Entry<K,V> nextEntry() { if (modCount != expectedModCount) throw
  57. 67.      * new ConcurrentModificationException(); Entry<K,V> e = next; if (e ==
  58. 68.      * null) throw new NoSuchElementException();
  59. 69.      *
  60. 70.      * if ((next = e.next) == null) { Entry[] t = table; while (index < t.length
  61. 71.      * && (next = t[index++]) == null) ; } current = e; return e; }
  62. 72.      */
  63. 73.

74. }

快速失败异常:当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常

解决方法:

A:迭代器删除

B:锁抢回来。集合自已删除。(前提:线程同步的集合)

Java 集合快速失败异常的更多相关文章

  1. Java最重要的21个技术点和知识点之JAVA集合框架、异常类、IO

    (三)Java最重要的21个技术点和知识点之JAVA集合框架.异常类.IO  写这篇文章的目的是想总结一下自己这么多年JAVA培训的一些心得体会,主要是和一些java基础知识点相关的,所以也希望能分享 ...

  2. Java笔记-快速失败and安全失败

    参考资料:http://blog.csdn.net/chenssy/article/details/38151189 快速失败 fail-fast 安全失败 fail-safe java.util包下 ...

  3. Java的快速失败和安全失败

    文章转自https://www.cnblogs.com/ygj0930/p/6543350.html 一:快速失败(fail—fast) 在用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的内容进 ...

  4. 面试题思考:java中快速失败(fail-fast)和安全失败(fail-safe)的区别是什么?

    一:快速失败(fail—fast) 在用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的内容进行了修改(增加.删除.修改),则会抛出Concurrent Modification Exceptio ...

  5. java中快速失败(fail-fast)和安全失败(fail-safe)的区别是什么?

    一:快速失败(fail—fast) 在用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的内容进行了修改(增加.删除.修改),则会抛出Concurrent Modification Exceptio ...

  6. (简单易懂)Java的快速失败(fail-fast)与安全失败,源码分析+详细讲解

    之前在程序中遇到快速失败的问题,在网上找解释时发现网上的问题总结都比较片面,故打算自己总结一个,也可以供以后参考. --宇的季节 首先什么是快速失败? 快速失败是为了提示程序员在多线程的情况下不要用线 ...

  7. java集合并发操作异常解决方法:CopyOnWriteArrayList

    一.我们知道ArrayList是线程不安全的,请编写一个不安全的案例并给出解决方案 HashSet与ArrayList一致 HashMap HashSet底层是一个HashMap,存储的值放在Hash ...

  8. 【原创】快速失败机制&失败安全机制

    这是why技术的第29篇原创文章 之前在写<这道Java基础题真的有坑!我求求你,认真思考后再回答.>这篇文章时,我在8.1小节提到了快速失败和失败安全机制. 但是我发现当我搜索" ...

  9. 一文搞懂所有Java集合面试题

    Java集合 刚刚经历过秋招,看了大量的面经,顺便将常见的Java集合常考知识点总结了一下,并根据被问到的频率大致做了一个标注.一颗星表示知识点需要了解,被问到的频率不高,面试时起码能说个差不多.两颗 ...

随机推荐

  1. OpenCV(5) 对比度和亮度

      公式: 两个参数 \alpha > 0 和 \beta 一般称作 增益 和 偏置 参数.我们往往用这两个参数来分别控制 对比度 和 亮度 .   #include "stdafx. ...

  2. Storm-166:Nimbus HA solution based on Zookeeper

    Nimbus HA feature is quite important for our application running on the storm cluster. So, we've bee ...

  3. 【转】vim格式化C代码

    转自:http://blog.chinaunix.net/uid-24774106-id-3396220.html 在自己的目录下编辑自己的.vimrc, vim ~/.vimrc 添加下面的几行: ...

  4. 拓展企业VR培训业务,这家VR训练公司StriVR完成500万美元融资!

    虚拟现实初创公司StriVR最近发布了新的企业VR训练产品项目,并宣布在刚刚结束的首轮融资中获得500万美元投资.由Signia Venture Partners领投,宝马i Venturesi.Ad ...

  5. ReLu(Rectified Linear Units)激活函数

    论文参考:Deep Sparse Rectifier Neural Networks (很有趣的一篇paper) 起源:传统激活函数.脑神经元激活频率研究.稀疏激活性 传统Sigmoid系激活函数 传 ...

  6. android 第三方 Im

    1.阿里百川 单聊.群聊.客服能力集成,仅需花费4小时,不收费,0成本接入,让App轻松拥有沟通能力,历经多次双十一考验,消息到达率100%,全年可用性高达99.99%,登录异常提醒,木马钓鱼网站监测 ...

  7. js中继承的几种用法总结(apply,call,prototype)

    一,js中对象继承 js中有三种继承方式 1.js原型(prototype)实现继承 <SPAN style="BACKGROUND-COLOR: #ffffff">& ...

  8. Android --RatingBar的使用

    1.效果图

  9. CodeForces 670D1 暴力或二分

    今天,开博客,,,激动,第一次啊 嗯,,先来发水题纪念一下 D1. Magic Powder - 1   This problem is given in two versions that diff ...

  10. pr高的2级域名站点如何做优化?

    优化方法: 二级域名的内容建设也需要细致化 很多人认为,优化二级域名没有优化顶级域名那么多工作,只需要发发外链就可以了,这可以说是一个误区.我们的目的是要优化二级域名到首页,让用户能够看到,如果我们的 ...