java.util.ConcurrentModificationException

经常我们要删除集合中的某些元素。有些可能会这么写。

   
  public void operate(List list){
        for (Iterator it = list.iterator(); it.hasNext();) {
            String str = (String)it.next();
            if (str.equals("chengang")){
                list.remove(str);
            }
        }
    }
   
  这种写法一运行就会报如下异常:
 
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:449)
 
  因为list在循环中的时候是不可以删除它的元素的。后来我是这样做的,一种很笨的方法,思路是这样的:创建一个List专门存放要被删除的元素,循环过后,用List.removeAll方法把元素删除。代码如下:
    public void operate(List list){
        List removeList= new ArrayList();
        for (Iterator it = list.iterator(); it.hasNext();) {
            String str = (String)it.next();
            if (str.equals("chengang")){
                removeList.add(str);
            }
        }
        list.removeAll(removeList);
    }
 
  这样也确实可以解决问题了,但是方法实在太笨重,其实可以有更简单的更高效的方法,就是用Iterator.remove方法,如下:
        for (Iterator it = list.iterator(); it.hasNext();) {
            String str = (String)it.next();
            if (str.equals("chengang")){
                it.remove();
            }
        }

 所以,你对Java的基础知识了解越多,代码就会写得越简洁。相反如果你的代码特别复杂,则方法或设计一定有问题。

----------------------------------------

通过查阅JDK,解释如下:
        public class ConcurrentModificationExceptionextends RuntimeException当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。

例如,某个线程在 Collection 上进行迭代时,通常不允许另一个线性修改该 Collection。通常在这些情况下,迭代的结果是不确定的。如果检测到这种行为,一些迭代器实现(包括 JRE 提供的所有通用 collection 实现)可能选择抛出此异常。执行该操作的迭代器称为快速失败 迭代器,因为迭代器很快就完全失败,而不会冒着在将来某个时间任意发生不确定行为的风险。

注意,此异常不会始终指出对象已经由不同 线程并发修改。如果单线程发出违反对象协定的方法调用序列,则该对象可能抛出此异常。例如,如果线程使用快速失败迭代器在 collection 上迭代时直接修改该 collection,则迭代器将抛出此异常。

    其实我并不明白这是什么意思,我的解释是通过al.add(new Point1(x1,y1,x2,y2))在主线程上修改迭代器.而while
(it.hasNext())在作图线程中进行迭代所以会造成异常.所义将Iterator it=al.iterator();移进paint()函数中竟然可以解决第一个问题.但是在百度上搜到一个高手是这么说的: 
     "Iterator 是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator 被创建之后会建立一个指向原来对象的单链索
引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast 原则 Iterator 会马上抛出 java.util.ConcurrentModificationException 异常。所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。但你可以使用 Iterator 本身的方法 remove() 来删除对象, Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。有意思的是如果你的 Collection / Map 对象实际只有一个元素的时候, ConcurrentModificationException 异常并不会被抛出。

这也就是为什么在 javadoc 里面指出: it would be wrong to write a program that depended on this exception for its correctness: ConcurrentModificationException should be used only to detect bugs.修改后: it.remove();"

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值