Как я могу исправить эту ошибку java.util.ConcurrentModificationException

Я получаю сообщение об ошибке в следующей строке. Я делаю процесс добавления к 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());
 Confusion10 июл. 2012 г., 08:42
Вы пропустили некоторый код, где вы на самом деле итерируете JSONArray, к которому вы добавляете элементы?
 Adriaan Koster10 июл. 2012 г., 08:33
что ты уже испробовал? Вы читали JavaDoc исключения ConcurrentModificationException?

Ответы на вопрос(7)

когда вы изменяете его одновременно.

ConcurrentModificationException генерируется, когда вы изменяете коллекцию в то же время, пока выполняете ее.

 10 июл. 2012 г., 08:27
как говорит devsundar, это не должно вызывать CME, если к jsonArr не доступен многопоточный доступ. Это?
 10 июл. 2012 г., 08:29
Из кода я вижу, что jsonArr только изменен, и к нему нет доступа одновременно. Если aliplane получает CME в упомянутой строке, то jsonArr следует изменить из другого места или потока.

который позволяет повторять и изменять один и тот же список

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

 25 сент. 2013 г., 14:14
Ответы, содержащие только ссылки, не приветствуются, поэтому ответы SO должны быть конечной точкой поиска решения (в отличие от еще одной остановки ссылок, которая, как правило, со временем устаревает). Пожалуйста, рассмотрите возможность добавления отдельного синопсиса здесь, сохраняя ссылку в качестве ссылки.

когда вы перебираете коллекцию и изменяете ту же коллекцию в цикле. Данный фрагмент кода не показывает этого, поэтому есть что-то еще выше или ниже, изменяющее коллекцию. Попробуйте объявить jsonArr прямо в том месте, где вы его создали.

Одной из возможных причин может быть экземпляр объекта jsonArr на уровне класса, доступ к которому осуществляется несколькими потоками. Объявите объект jsonArr, в котором он создан.

Редактировать: Сделать jsonArr локальной переменной.

 aliplane10 июл. 2012 г., 09:49
доступ к коду из сервлета. Я использую автозаполнение для.
 10 июл. 2012 г., 16:10
При кодировании в многопоточной среде, такой как веб-приложения, область ваших переменных должна быть как можно более локальной. Вы не столкнетесь с такими проблемами.

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 -

This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible.

For example, it is not generally permssible for one thread to modify a Collection while another thread is iterating over it. In general, the results of the iteration are undefined under these circumstances. Some Iterator implementations (including those of all the collection implementations provided by the JRE) may choose to throw this exception if this behavior is detected. Iterators that do this are known as fail-fast iterators, as they fail quickly and cleanly, rather that risking arbitrary, non-deterministic behavior at an undetermined time in the future.

Решение Вопроса

с которой я часто сталкивался при перепрограммировании. причина или детали этого исключения довольно ясны. Нельзя изменять коллекцию (вы добавляете новый элемент), пока она повторяется. По крайней мере, синтаксис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);
 aliplane10 июл. 2012 г., 11:16
было очень полезно :)
 10 июл. 2012 г., 11:03
Что вы имеете в виду описательный?
 aliplane10 июл. 2012 г., 11:00
ответить слишком описательно. спасибо

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");
}

В случае передачи фактического списка мы можем передать клон списка для итерации.

listForIteration = list.clone ();

// Делаем операцию ..

Ваш ответ на вопрос