2011-01-13 3 views
0

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

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

Класс Meeting и Примечание Класс может нравится это:

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 если я пытаюсь сделать больше Встречу в основной, так я изменяет Littel в классе Примечание, любит это:

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) { 
      } 
    } 
    } 

}

+1

Хотя за исключением было то, что привело вас сюда, я также должен указать, что ваша логика не идеальна, поскольку [вы не должны публиковать ссылку на «это» во время строительства] (http://www.ibm.com/developerworks/java/library /j-jtp0618.html), если вы хотите использовать несколько потоков, так как это может сломать инварианты, которые должны «всегда» удерживаться. Кроме того, отступы ваш код правильно и последовательно поможет читаемость удивительной суммы. –

+0

Спасибо Andrzej и Извините, что мой код не размещен должным образом. Многопроцессы не приводят к ConcurrentModificationException в моей программе. Это происходит, когда я перебираю список в классе Note и, возможно, новый объект собрания хочет добавить себя в список – echo

ответ

4

Из JavaDoc

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

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

+0

+1, это именно оно. Один из способов решения этой проблемы - взять * копию * рассматриваемой коллекции, а затем перебрать копию (чтобы элементы могли быть добавлены в оригинал без проблем). Но обычно это признак того, что логический поток не так ясен, как может быть, поэтому стоит подумать о том, почему * вы мутируете во время итерации и как еще вы можете достичь своих целей. –

0

Читайте, что написал @ Нави.

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

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

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

+0

Вы можете удалить элементы из списка (при повторении), если вы выполняете итерацию с помощью интерфейса Iterator, и используете метод remove() Iterator. Добавление элементов не поддерживается интерфейсом Iterator. – Atticus

0

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

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

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

Смежные вопросы