2013-08-20 2 views
0

У меня есть код, как показано ниже, и я получаю ConcurrentModificationException, особенно в линии для (String файла: файлы)ConcurrentModificationException в HashSet

Я ничего для «файл» не изменяется при выполнении итерации, так почему исключение будет вызвано и как его избежать? Спасибо за любое предложение!

int getTotalLength(final HashSet<String> files) { 
     int total = 0; 
     int len; 
     for (String file : files) { 
      len = getLength(file); 
      if (len != Long.MIN_VALUE) { 
       total += len; 
      } 
     } 
     return total; 
    } 




     int getLength(String file) { 
     int len = Long.MIN_VALUE; 

     if (file == null) { 
      return len; 
     } 

     File f = new File(file); 

     if (f.exists() && f.isFile()) { 
      len = f.length(); 
     } 

     return size; 
    } 
+1

У вас есть другие темы, которые могут быть изменены одновременно? –

+0

да, это возможно, но я сделал окончательный вариант hashSet ... не помешает ли ему модифицироваться? –

+0

ConcurrentModification находится на вашем HashSet, а не на вашем файле –

ответ

3

Отсносящийся вам комментировать, объявляя final HashSet<String> files делает переменную files финалом - это означает, что вы не можете присвоить другой объект этой переменной внутри рамки этой переменной. HashSet сам по себе является изменяемым объектом и может быть изменен - ​​он не имеет ничего общего с окончательным модификатором (ссылка на заданный объект itselt все тот же). Если вы хотите работать на одном и том же объекте (тот же хэшсет), используйте synchronized блоки или методы.

Вообще говоря, вы не можете изменять коллекцию (в том же или другом потоке), которые повторяются с помощью цикла for в for-each.

+0

Вызывающих (скажем, Callera), что вызывает getTotalLength() является уже синхронизирован методом и Callera не изменяет коллекцию, но callerB, что вызывает Callera изменяет коллекцию ... кода выглядит следующим образом ничтожной callerB() { изменить HashSet; callerA(); } аннулируется Callera() { называет getTotalLength(), где я получаю исключение } –

+0

Должен ли я использовать синхронизированный блок в вызывающем абоненте B таким образом, что недействительного callerB() { синхронизированных (HashSet) { модифицировать HashSet ; callerA(), который выполняет итерацию hashSet; } } –

+0

Если метод (как вы ссылались на «синхронизированный метод») синхронизирован, это означает, что если один поток выполняет такой метод (является «внутри»), ни один другой поток не может выполнить этот метод, пока предыдущее исполнение не закончится. Если вы синхронизировали два разных метода (с ключевым словом 'synchronized' в сигнатуре метода), они не синхронизируются друг с другом. Вы должны явно синхронизировать свой код на общем объекте с обоими методами, которые вы хотите синхронизировать. – Antoniossss

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