如何解决此错误java.util.ConcurrentModificationException

时间:2012-07-10 06:15:03

标签: java exception arrays concurrentmodification

我在以下行收到错误。 我正在做添加到jsonarray的过程。 请帮帮我。

jsonArr=new JSONArray();
if(req.getSession().getAttribute("userses")!=null){
    String name=(req.getParameter("name")==null?"":to_EnglishName(req.getParameter("name").toUpperCase()));
    if(!name.equals("")){
        for(Book c:GlobalObjects.bookList){
            if(c.getBookName().startsWith(name)){
                    jsonObjec=new JSONObject();
                    jsonObjec.put("label",c.getBookName());
                    jsonObjec.put("value", c.getId());
                    jsonArr.add(jsonObjec);//java.util.ConcurrentModificationException
            }
        }
    }
}
jsonArr.write(res.getWriter());

7 个答案:

答案 0 :(得分:13)

这是我在重新编程时经常遇到的错误。这个例外的原因或细节非常清楚。在迭代时不允许修改集合(您正在添加新元素)。至少语法for不支持这样做。

要解决您的问题,我认为有两种方法很简单。

1)。而不是使用for语句循环,更好的方法是使用迭代器来避免ConcurrentModificationException。

    Iterator<Book> iterator = bookList.iterator();
    while(iterator.hasNext()){
      Book c = iterator.next();
      if(c.getBookName().startsWith(name)){
                jsonObjec=new JSONObject();
                jsonObjec.put("label",c.getBookName());
                jsonObjec.put("value", c.getId());
                jsonArr.add(jsonObjec);
        }
    }

2)。在循环播放时,不要添加它。

     List list = new ArrayList<>();
     for(Book c:GlobalObjects.bookList){
        if(c.getBookName().startsWith(name)){
                jsonObjec=new JSONObject();
                jsonObjec.put("label",c.getBookName());
                jsonObjec.put("value", c.getId());
                list.add(jsonObjec);//java.util.ConcurrentModificationException
        }
     }
     jsonArr.addAll(list);

答案 1 :(得分:3)

要解决此问题,请确保If your collection is not thread safe then it must not get modified with another thread when some other thread is iterating over this collection

有两种方法可以解决此问题 -

1)一种解决方案是同步对集合的所有访问

2)使用像CopyOnWriteArrayList

这样的线程安全集合

来自Java Doc -

  

检测到并发的方法可能抛出此异常   在不允许进行此类修改时修改对象。

     

例如,一个线程修改a通常不允许   集合,而另一个线程正在迭代它。一般来说,   在这些情况下,迭代的结果是不确定的。一些   迭代器实现(包括所有集合的实现)   JRE提供的实现可以选择抛弃它   检测到此行为的异常。执行此操作的迭代器是   称为失败快速迭代器,因为它们快速而干净地失败   冒着不确定的任意,非确定性行为的风险   未来的时间。

答案 2 :(得分:2)

当您在集合上进行迭代并在循环中修改相同的集合时,会出现ConcurrentModificationException。给定的代码段没有显示,因此在修改集合之上或之下还有其他内容。尝试在实例化它的地方声明jsonArr。

一个可能的原因可能是jsonArr实例Object是类级别,并且可以被多个线程访问。声明实例化它的jsonArr对象。

编辑:使jsonArr成为局部变量。

答案 3 :(得分:1)

还有一种方法,即 通过实际列表,我们可以通过列表的克隆进行迭代。

listForIteration = list.clone();

//操作..

答案 4 :(得分:0)

您是否从另一个线程访问jsonArr?即,当你同时修改它时,迭代jsonArr。

在迭代时同时修改集合时抛出ConcurrentModificationException。

答案 5 :(得分:0)

或者使用允许迭代和修改相同列表的ListIterator

http://docs.oracle.com/javase/6/docs/api/java/util/ListIterator.html

答案 6 :(得分:0)

只需使用java.util.concurrent.CopyOnWriteArrayList

List<String> empList = new CopyOnWriteArrayList<>();
empList.add("Mojtaba");
empList.add("Mojtabye");
empList.add("Yeganeh");

for (String item : empList) {
    System.out.println(item);
    empList.add("test");
}