Это хороший способ предотвратить ConcurrentModificationException - PullRequest
0 голосов
/ 13 января 2011

Другой вопрос о синхронизированном . У меня также есть run () в классе Note, потому что я хочу выводить каждый элемент в заметках каждые 5 минут. Но я всегда получаю исключение: java.util.ConcurrentModificationException, если я пытаюсь проводить больше встреч в основном. поэтому я применяю синхронизированный к списку заметки, которые могут быть добавлены новым собранием, когда я перебираю заметки. Мой метод запуска такой:

Правильно ли это указано в списке записей для синхронизации, чтобы предотвратить ConcurrentModificationException? (В моей программе это работает. Сейчас я не получаю этого исключения)

Классу Meeting и Note может понравиться этот класс:

public class Meeting{

    public Meeting(Note note_1,Note note_2){

                 note_1.addElement(this);

                 note_2.addElement(this);}

                 //another method hier 

                  }

public class Note implements Runnable{

    public final List<Meeting> notes = new ArrayList<Meeting>();

    public void addElement(Meeting n){

               entries.add(n);
              }

   @Override

   public void run(){
             while(true) {
             for(Meeting n : notes){

                 System.out.println(n.toString);}

                 }

             try{ Thread.sleep(10);}

             }

           }
          }

Я всегда получаю сообщение об ошибке исключения исключение: java.util.ConcurrentModificationException если я пытаюсь сделать больше Встреча в основном, поэтому я изменяю немного в классе Примечание, нравится это:

  private  static final List<Entry> entries = Collections.synchronizedList(new ArrayList<Entry>());

и выполняется ()

@Override
public void run() {
    while(true){
        synchronized(notes){
            for(Entry n : entries){
                 //do something
                 }
            }
            try {   
                Thread.sleep(10);  
         } catch (InterruptedException e ) {
            } 
     }
   }

}

Ответы [ 3 ]

4 голосов
/ 13 января 2011

Из javadoc

Обратите внимание, что это исключение не всегда указывает на то, что объект был одновременно изменен другим потоком.Если один поток выдает последовательность вызовов методов, которая нарушает контракт объекта, объект может вызвать это исключение.Например, если поток изменяет коллекцию напрямую, в то время как он выполняет итерацию по коллекции с помощью итератора с быстрым отказом, итератор отбросит это исключение.

Это означает, что нельзя изменять коллекцию в цикле, а выполнять ее итерацию в одно и то же время, даже в одном потоке.

0 голосов
/ 13 января 2011

Я использовал CopyOnWriteArrayList раньше, когда сталкивался с такой проблемой.

Это делает полную копию базового массива для каждой записи, так что это не очень эффективно, ноЯ нашел его очень полезным для определенных обстоятельств (например, для класса, который управляет уведомлением о специальных событиях для некоторых других классов)

Этот массив никогда не изменяется в течение времени жизни итератора, поэтому вмешательство невозможно иИтератор гарантированно не выбрасывает ConcurrentModificationException

0 голосов
/ 13 января 2011

Прочитайте, что написал @Navi.

В двух словах - НИКОГДА не удаляйте / не добавляйте элементы коллекции для каждого цикла.

Однажды у меня была такая проблема, и я решил использовать http://code.google.com/p/google-collections/ Там есть некоторые функции map / filter (если я помню, что методы были в библиотеке Collections2).

Если вы не хотите делать все правильно, вы всегда можете использовать технику итераторов старой школы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...