2012-07-10 109 views
2

我在下面一行发生错误。 我正在做添加到jsonarray的过程。 请帮帮我。我该如何解决这个错误java.util.ConcurrentModificationException

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()); 
+0

你尝试过这么远吗?你读过ConcurrentModificationException的JavaDoc吗? – 2012-07-10 06:33:54

+0

你是否遗漏了一些代码,你实际上是在迭代你添加项目的JSONArray? – Confusion 2012-07-10 06:42:30

回答

11

这是我在重新编程时经常遇到的错误。这个例外的原因或细节非常清楚。在迭代过程中不允许修改集合(您正在添加一个新元素)。至少语法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); 
+0

回复太描述性了。感谢 – aliplane 2012-07-10 09:00:26

+0

你的意思是描述性的? – 2012-07-10 09:03:29

+0

是非常有帮助:) – aliplane 2012-07-10 09:16:19

0

你是从另一个线程访问jsonArr吗?即在您同时修改jsonArr时迭代。

如果在迭代迭代时同时修改集合,则会引发ConcurrentModificationException。

+0

devsundar说,除非jsonArr被多线程访问,否则这不应该导致CME。是吗? – MJB 2012-07-10 06:27:09

+0

从代码我看到,jsonArr只被修改,并没有在同一时间被访问。如果铝飞机在所提到的线上获得了CME,那么应该从另一个位置或线程修改jsonArr。 – 18bytes 2012-07-10 06:29:59

2

当您迭代集合并且修改循环中的相同集合时,会发生ConcurrentModificationException。给定的代码片段没有显示,所以在修改集合上面或下面有其他内容。尝试在实例化它的地方声明jsonArr。

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

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

+0

访问Servlet中的代码。我使用自动完成功能。 – aliplane 2012-07-10 07:49:26

+0

在多线程环境(如Web应用程序)中进行编码时,请将变量的作用域尽可能保持为本地。你不会遇到这样的问题。 – devang 2012-07-10 14:10:03

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文件 -

这种异常可能会被检测到并发的 修改对象的方法抛出,修改是不允许的。

例如,一个线程修改一个 集合,而另一个线程正在迭代它时,通常是不可能的。通常,在这些情况下,迭代的结果是不确定的。某些 迭代器实现(包括由JRE提供的所有实现集合 实现中的那些实现)可能会选择抛出此异常(如果检测到此行为)。这样做的迭代器是 ,称为失败快速迭代器,因为它们快速且干净地失败,而在未来未确定的 时间冒着任意的非确定性行为冒险。

0

或者使用的ListIterator,它允许迭代和修改同一个列表

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

+1

只有链接的答案是不鼓励的,所以答案应该是搜索解决方案的终点(而另一个引用的中途停留时间往往会过时)。请考虑在此添加独立的摘要,并将链接保留为参考 – Alex 2013-09-25 12:14:59

0

而且另一种方式是存在的,即 insted的经过实际列表中,我们可以通过列表的克隆为迭代。

listForIteration = list.clone();

//做手术..

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"); 
} 
相关问题