黑马程序员技术交流社区

标题: 集合中的并发执行异常问题 [打印本页]

作者: 孙飞    时间: 2012-7-4 20:42
标题: 集合中的并发执行异常问题
本帖最后由 feigecal 于 2012-7-4 23:11 编辑

今天练习教程,出了问题,想不出原因,还请大家帮忙
  1. import java.util.*;
  2. class YiChang
  3. {
  4. public static void sop(Object obj)
  5. {
  6. System.out.println(obj);
  7. }
  8. public static void main(String[] args)
  9. {
  10. ArrayList al=new ArrayList();
  11. al.add("ok1");
  12. al.add("ok2");
  13. al.add("ok3");
  14. sop(al);
  15. Iterator it=al.iterator();
  16. while(it.hasNext())
  17. {
  18. Object obj=it.next();
  19. if (obj.equals("0k2"))
  20. {
  21. al.add("ok4");
  22. it.remove();
  23. }
  24. sop(obj);
  25. }
  26. sop(al);
  27. }
  28. }
复制代码

在迭代器操作集合元素的时候如果再用集合对象的方法来操作不是会发生并发执行异常吗?为什么我在迭代器取元素时用集合对象去添加元素al.add("ok4");没有抛出异常呢?而且这句没执行,下面那句it.remove();也没执行,为什么啊?运行结果如下图:

作者: yulu53    时间: 2012-7-4 21:00
if (obj.equals("0k2")) 写错了 应该是o
作者: 周刚    时间: 2012-7-4 21:08
帮楼主仔细检查了一遍,原来是第19行ok写成0k了!!
import java.util.*;

class YiChang {
        public static void sop(Object obj) {
                System.out.println(obj);
        }

        public static void main(String[] args) {
                ArrayList al = new ArrayList();
                al.add("ok1");
                al.add("ok2");
                al.add("ok3");
                sop(al);
                Iterator it = al.iterator();
                while (it.hasNext()) {
                        Object obj = it.next();
                        if (obj.equals("ok2")) {                                
                                                     al.add("ok4");
                                it.remove();
                        }
                        sop(obj);
                }
                sop(al);
        }
}

你要的报错结果如下:
[ok1, ok2, ok3]
ok1
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
at java.util.AbstractList$Itr.remove(Unknown Source)
at YiChang.main(YiChang.java:19)

作者: 万宝东    时间: 2012-7-4 21:09
我晕了,原来是你代码出现手误了啊。19.if (obj.equals("0k2"))这句,原本是ok2,你写成了 0k2,所以,这个if语句的结果全是false,循环内的语句就不执行。所以没有报错,也没有执行那两行代码。
至于用迭代器时,用集合操作元素,产生并发操作时,会报异常,这个是真的。在毕老师视频中有讲解。视频详见毕老师基础视频的day16的(集合框架-ListIterator接口)这个视频中有讲解。我的这个是毕老师新版视频,就是那个号称“历经5年锤炼--史上最适合初学者入门的Java基础视频”这个视频,老版本的视频在哪一集我不太清楚。
作者: 周刚    时间: 2012-7-4 21:09
哥们儿,你是宜昌滴???那儿我熟啊!!!!
作者: 任文杰    时间: 2012-7-4 21:45
本帖最后由 RWJ2012 于 2012-7-4 21:52 编辑
  1. import java.util.*;
  2. import java.util.concurrent.CopyOnWriteArrayList;

  3. class YiChang {
  4.         public static void sop(Object obj) {
  5.                 System.out.println(obj);
  6.         }

  7.         public static void main(String[] args) {
  8.                
  9.                 //ArrayList al = new ArrayList();
  10.                CopyOnWriteArrayList[/color]<String> al = new CopyOnWriteArrayList<String>();
  11.                 al.add("ok1");
  12.                 al.add("ok2");
  13.                 al.add("ok3");
  14.                 sop(al);
  15.                 //Iterator it = al.iterator();
  16.                 Iterator<String> it = al.iterator();
  17.                 while (it.hasNext()) {
  18.                         Object obj = it.next();
  19.                         
  20.                         if (obj.equals("ok2")) {
  21.                                 al.add("ok4");
  22.                                 //it.remove();                             
  23.                                 al.remove("ok4");
  24.                        }
  25.                         sop(obj);
  26.                 }
  27.                 sop(al);
  28.         }
  29. }
复制代码
这样改的话就没问题了,普通集合列表(ArrayList)不可以并发操作,而CopyOnWriteArray这个类是jdk1.5增加的并发集合类,可以执行并发操作,即可以在遍历集合列表的过程中对集合列表进行增加和删除操作。代码中用it.remove()达到删除集合列表最后一个元素的目的,是不可取的,查看API文档:Removes from the underlying collection the last element returned by this iterator (optional operation). This method can be called only once per call to next. The behavior of an iterator is unspecified if the underlying collection is modified while the iteration is in progress in any way other than by calling this method.大概意思是说:在iterator执行的过程中,用iterator来删除集合列表最后一个元素的结果是不确定的,可能会抛出异常 java.lang.UnsupportedOperationException,而如果改为al.remove("ok4")就没问题了。
作者: 孙飞    时间: 2012-7-4 23:09
周刚 发表于 2012-7-4 21:09
哥们儿,你是宜昌滴???那儿我熟啊!!!!

不是啊,呵呵




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2