`
fxly0401
  • 浏览: 149956 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

(转)ConcurrentModificationException 问题

 
阅读更多
原文地址:http://www.cnblogs.com/sunwufan/archive/2012/05/21/2511747.html
当考虑到列表中需要修改的元素很多时,可以考虑上一篇博文:
通过CopyOnWriteArrayList,在遍历过程中,对list元素进行删除和添加操作

方法一(效率不高):
这个问题是说,你不能在对一个List进行遍历的时候将其中的元素删除掉 解决办法是,你可以先将要删除的元素用另一个list装起来,等遍历结束再remove掉 可以这样写

List delList = new ArrayList();//用来装需要删除的元素
for(Information ia:list)
    if(ia.getId()==k){
          n++;
          delList.add(ia);
     }
list.removeAll(delList);//遍历完成后执行删除


//////////////////////////////////////////////////////////////////////////////////////////////////////////////
方法二:同步操作list时,一边迭代remove,一边新增.那么会报错 java.util.ConcurrentModificationException

查看api发现vector有个好方法可以解决这个错误.

首先是用arraylist

//    private  Vector list;//两种list方式
    private  List list;
   
   
    public  void init(){
//        list = new Vector();
        list = new ArrayList();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("e");
        list.add("f");
    }
   
    public  void removeIt(){//iterator
        Iterator it = list.iterator();
        for(int i=0;it.hasNext();i++){
            String a = (String)it.next();
            System.out.println(a);
            if(a.equals("c")){
                //list.remove(a);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                }
                it.remove();
                System.out.println("remove c");
            }
        }
       
    }
   
//    public void removeEm(){//enumeration
//        Enumeration e = list.elements();
//        for(int i=0;e.hasMoreElements();i++){
//            String a = (String)e.nextElement();
//            System.out.println(a);
//            if(a.equals("c")){
//                try {
//                        Thread.sleep(1000);
//                } catch (InterruptedException ee) {
//                }
//                list.remove(a);
//                System.out.println("remove c");
//            }
//        }
//    }
   
    public  void add(){//先用迭代,再添加
        try {
            Thread.sleep(500);
        } catch (Exception e) {
            // TODO: handle exception
        }
        list.add("c");
        System.out.println("add c");
    }
   
   
   
    public void run() {
        removeIt();
//        removeEm();
    }


    public static void main(String[] args) {
        TestConcurrentModificationException t = new TestConcurrentModificationException();
        t.init();
        t.start();
        t.add();
    }

运行结果:
a
b
c
add c
Exception in thread "Thread-0" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
at java.util.AbstractList$Itr.remove(Unknown Source)
at test.TestConcurrentModificationException.removeIt(TestConcurrentModificationException.java:33)
at test.TestConcurrentModificationException.run(TestConcurrentModificationException.java:69)



其次是vector


    private  Vector list;//两种list方式
//    private  List list;
   
   
    public  void init(){
        list = new Vector();
//        list = new ArrayList();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("e");
        list.add("f");
    }
   
    public  void removeIt(){//iterator
        Iterator it = list.iterator();
        for(int i=0;it.hasNext();i++){
            String a = (String)it.next();
            System.out.println(a);
            if(a.equals("c")){
                //list.remove(a);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                }
                it.remove();
                System.out.println("remove c");
            }
        }
       
    }
   
    public void removeEm(){//enumeration
        Enumeration e = list.elements();
        for(int i=0;e.hasMoreElements();i++){
            String a = (String)e.nextElement();
            System.out.println(a);
            if(a.equals("c")){
                try {
                        Thread.sleep(1000);
                } catch (InterruptedException ee) {
                }
                list.remove(a);
                System.out.println("remove c");
            }
        }
    }
   
    public  void add(){//先用迭代,再添加
        try {
            Thread.sleep(500);
        } catch (Exception e) {
            // TODO: handle exception
        }
        list.add("c");
        System.out.println("add c");
    }
   
   
   
    public void run() {
//        removeIt();
        removeEm();
    }


    public static void main(String[] args) {
        TestConcurrentModificationException t = new TestConcurrentModificationException();
        t.init();
        t.start();
        t.add();
    }

运行结果:

a
b
c
add c
remove c
e
f
c
remove c
api上说,
由 Vector 的 iterator 和 listIterator 方法所返回的迭代器是快速失败的:如果在迭代器创建后的任意时间从结构上修改了向量(通过迭代 器自身的 remove 或 add 方法之外的任何其他方式),则迭代器将抛出 ConcurrentModificationException。因此,面对并发的修改,迭代器很快就完全失败,而不是冒着在将来不确定的时间任意发生 不确定行为的风险。Vector 的 elements 方法返回的 Enumeration 不是 快速失败的。
注意,迭代器的快速失败行为不能得到保证,一般来说,存在不同步的并发修改时,不可能作出任何坚决的保证。快速失败迭代器尽最大努力抛出 ConcurrentModificationException。因此,编写依赖于此异常的程序的方式是错误的,正确做法是:迭代器的快速失败行为应该仅用于检测 bug。


当然如果使用其他的集合,那就没有什么好办法了.只有存放起来,每次取一个list对象,并不是实时.
分享到:
评论

相关推荐

    java.util.ConcurrentModificationException 解决方法

    java.util.ConcurrentModificationException 解决方法 在使用iterator.hasNext()操作迭代器的时候,如果此时迭代的对象发生改变,比如插入了新数据,或者有数据被删除。 则使用会报以下异常: ...例如以下程序(转

    fastJson全部资料

    **FastJson 深度解析** FastJson 是阿里巴巴开源的一款高效、功能强大的 JSON 库,它在 Java 开发中被广泛使用,特别是在处理 JSON 数据序列化与反序列化时。这个压缩包包含了 FastJson 的全部资料,对于学习和理解...

    Java 常见问题解决集合.docx

    **5.2 问题:** "ConcurrentModificationException" **解决:** 在遍历集合时同时修改它会导致这个异常。解决方案包括: - **使用线程安全集合:** 使用线程安全的集合类,如`ConcurrentHashMap`。 - **迭代器的...

    Java Web应用中常见的错误和异常问题处理.zip

    - **并发异常**:如ConcurrentModificationException,当多个线程访问同一资源时,如果没有适当的同步控制,可能会出现问题。使用synchronized关键字、Lock机制或并发集合来解决。 - **死锁**:多个线程互相等待...

    Java白板程序(有Bug,真的有Bug!!!)

    常见的问题可能包括但不限于:空指针异常(NullPointerException)、类型转换异常(ClassCastException)、数组越界异常(ArrayIndexOutOfBoundsException)、并发修改异常(ConcurrentModificationException)等。...

    java学习中的错误查找

    5. **并发问题**:多线程编程中,共享资源的并发访问可能导致数据不一致、死锁等问题。使用synchronized关键字、volatile修饰符、Lock接口等工具管理并发访问,保证线程安全。 6. **异常处理**:Java中的异常处理是...

    Java中增强for循环的实现原理和坑详解

    如果在遍历集合或数组时,修改了集合或数组的内容,这可能会引发ConcurrentModificationException异常。这种异常是在运行时抛出的,而不是在编译期。 例如,在遍历集合时,修改集合的内容可能会引发...

    088-Java业务开发常见错误100例

    4. **并发问题**:在多线程环境中,不恰当的共享资源访问可能导致数据不一致,如`ConcurrentModificationException`。使用`synchronized`关键字或者并发集合可以防止这类问题。 5. **IO异常**:在处理输入/输出时,...

    藏经阁-Java开发手册(嵩山版)灵魂15问-123.pdf

    但是,如果我们在foreach循环中进行元素的remove/add操作,可能会出现ConcurrentModificationException。因为foreach循环不允许在遍历过程中修改数据。如果我们需要在foreach循环中进行元素的remove/add操作,我们...

    《Java开发手册(泰山版)》灵魂13问.pdf

    10. serialVersionUID字段的修改问题:阿里巴巴禁止开发人员修改serialVersionUID字段的值,因为这个字段用于序列化版本控制,如果随意更改会导致序列化与反序列化时出现问题。正确的做法是在类的序列化形式变更时才...

    java对于Json文件的解析范例

    - 遍历方式:推荐使用迭代器`Iterator`遍历ArrayList,而不是`for-each`循环,因为`for-each`在删除元素时可能导致ConcurrentModificationException。 以上内容涵盖了Java解析JSON的基本方法、时间戳转换、文件...

    java环境报错大全下载地址

    10. **ConcurrentModificationException**:在多线程环境下,当一个线程正在修改集合,而另一个线程尝试遍历同一集合时,会抛出此异常。使用并发控制或使用不可变集合来避免。 以上仅是Java环境报错中的一部分,...

    Java.Bug模式详解

    6. **集合操作错误**:在遍历集合时修改集合会导致ConcurrentModificationException。使用迭代器或Collections.unmodifiableList()等方法可以避免这类问题。 7. **类型转换异常**:强制类型转换不当可能导致...

    java常见的异常

    12. **ConcurrentModificationException**:在并发修改集合时,如果一个线程正在迭代集合,而另一个线程同时对集合进行修改,会出现此异常。推荐使用`CopyOnWriteArrayList`或`ConcurrentHashMap`等并发友好的集合类...

    Java 常见疑难解Java 常见疑难解

    - **遍历与修改集合**:在迭代器遍历集合时修改集合会导致ConcurrentModificationException。使用Iterator的remove()方法或者CopyOnWriteArrayList/CopyOnWriteArraySet等并发友好的集合可以解决此问题。 - **集合...

    java名企面试题

    面试中可能会涉及到并发修改(ConcurrentModificationException)、迭代器、集合排序、泛型、JDK新版本中集合的优化等内容。 3. **多线程**:Java多线程是常考知识点,包括线程的创建、同步、互斥、死锁,以及...

    HashMap源码分析系列-第四弹:HashMap多线程解决方案.docx

    3. **并发修改异常**:当一个线程正在遍历`HashMap`时,另一个线程对其进行了修改,则可能会抛出`ConcurrentModificationException`异常。 #### 三、解决方案概述 针对以上提到的问题,有多种不同的解决方案可以...

    Collection集合习题答案 1

    在遍历集合时,通常推荐使用Iterator而不是直接通过集合的索引进行操作,因为这样可以避免并发修改异常(ConcurrentModificationException)。 在题目中,给出了三个练习: 1. 练习一要求简述集合框架,我们已经...

    Java的线程安全与不安全集合.docx

    线程不安全则表示在多线程环境下,如果不采取额外的同步措施,就可能引发数据竞争和其他并发问题。 线程不安全集合: 1. `ArrayList`: 这是一个动态数组实现的列表,其添加、删除和修改操作不是线程安全的。在并发...

Global site tag (gtag.js) - Google Analytics