2013-09-06 3 views
0

Я получаю ConcurrentModificationException, итерации через HashMap.ConcurrentModificationException при повторении через HashMap

Как это исправить?

public void stopAllPlaying(int fadeDurationInMs) 
{ 
    for(PlayThread thread : threadMap.values()) { 
     if(thread != null) { 
      thread.fadeOut(fadeDurationInMs); 
     } 
    } 
    threadMap.clear(); 
} 

UPDATE:

К сожалению, с помощью lock, кажется, не зафиксировали его. Я скопировал ниже сообщение об ошибке

09-06 01:05:51.366: E/AndroidRuntime(1307): FATAL EXCEPTION: main 
09-06 01:05:51.366: E/AndroidRuntime(1307): java.util.ConcurrentModificationException 
09-06 01:05:51.366: E/AndroidRuntime(1307):  at java.util.HashMap$HashIterator.nextEntry(HashMap.java:796) 
09-06 01:05:51.366: E/AndroidRuntime(1307):  at java.util.HashMap$ValueIterator.next(HashMap.java:828) 
09-06 01:05:51.366: E/AndroidRuntime(1307):  at com.example.myapp.AudioTrackPlayer.stopAllPlaying(AudioTrackPlayer.java:141) 
09-06 01:05:51.366: E/AndroidRuntime(1307):  at com.example.myapp.MyApp.stopAllSounds(MyApp.java:119) 
09-06 01:05:51.366: E/AndroidRuntime(1307):  at com.example.myapp.MainActivity.stopPlayback(MainActivity.java:114) 
09-06 01:05:51.366: E/AndroidRuntime(1307):  at com.example.myapp.MainActivity.onConfigurationChanged(MainActivity.java:451) 
09-06 01:05:51.366: E/AndroidRuntime(1307):  at android.app.ActivityThread.performConfigurationChanged(ActivityThread.java:3397) 
09-06 01:05:51.366: E/AndroidRuntime(1307):  at android.app.ActivityThread.handleConfigurationChanged(ActivityThread.java:3542) 
09-06 01:05:51.366: E/AndroidRuntime(1307):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1121) 
09-06 01:05:51.366: E/AndroidRuntime(1307):  at android.os.Handler.dispatchMessage(Handler.java:99) 
09-06 01:05:51.366: E/AndroidRuntime(1307):  at android.os.Looper.loop(Looper.java:150) 
09-06 01:05:51.366: E/AndroidRuntime(1307):  at android.app.ActivityThread.main(ActivityThread.java:4263) 
09-06 01:05:51.366: E/AndroidRuntime(1307):  at java.lang.reflect.Method.invokeNative(Native Method) 
09-06 01:05:51.366: E/AndroidRuntime(1307):  at java.lang.reflect.Method.invoke(Method.java:507) 
09-06 01:05:51.366: E/AndroidRuntime(1307):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) 
09-06 01:05:51.366: E/AndroidRuntime(1307):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) 
09-06 01:05:51.366: E/AndroidRuntime(1307):  at dalvik.system.NativeStart.main(Native Method) 

UPDATE 2:

мне нужно, чтобы добавить блокировку всех тех случаях, когда Hashmap был быть модифицированными!

+0

Вы пробовали какие-либо синхронизирующие техники? «синхронизированное» ключевое слово, замок, семафор, что-нибудь? – Fildor

+0

См. Мой обновленный ответ. Я думаю, вы пропустили использование. – Fildor

ответ

1
private final Lock lock = new ReentrantLock(); 
public void stopAllPlaying(int fadeDurationInMs) 
{ 
    lock.lock(); 
    try{ 
     for(PlayThread thread : threadMap.values()) { 
      if(thread != null) { 
       thread.fadeOut(fadeDurationInMs); 
      } 
     } 
     threadMap.clear(); 
    } 
    finally{ 
    lock.unlock(); 
    } 
} 

Это должно выполнить эту работу.

Вы должны заблокировать все другие способы использования threadMap таким же образом с тем же экземпляром блокировки.

ПРИМЕЧАНИЕ: Это не единственный способ сделать синхронизацию.

Смотрите также http://developer.android.com/reference/java/util/concurrent/locks/Lock.html

Вы можете найти это полезно, тоже: http://docs.oracle.com/javase/tutorial/essential/concurrency/sync.html

+0

Спасибо Fildor - это отлично работает. Любая идея, насколько это эффективно? Будет ли лучше блокировать поток, чтобы не блокировать мой поток пользовательского интерфейса? – fxfuture

+0

Более эффективным было бы использование некоторого алгоритма без блокировки. Лично я считаю использование Lock довольно эффективным, пока заблокированный блок достаточно мал (в LOC и времени выполнения). По крайней мере, это более эффективно, чем блокирование всего экземпляра с использованием ключевого слова synchronized. – Fildor

+0

Я действительно не знаю, что вы имеете в виду с «блокировкой самой нити». На самом деле вы _are_ «блокируете поток». То есть Если Thread1 ввел заблокированный блок, Thread2 будет блокироваться в 'lock.lock()' до тех пор, пока Thread1 не освободит блокировку с помощью 'lock.unlock()'. – Fildor

0

Вы не можете заблокировать GUI нить долго, как это киосков все приложения. «fadeOut» не звучит как нечто мгновенное.

Каскад двух потоков: поток GUI вызывает промежуточный поток, и этот промежуточный поток затем вызывает stopAllPlaying, ожидая блокировки, если необходимо. Промежуточная нить может ждать произвольное длительное время.

+0

Спасибо Audruis, но я не уверен, что понимаю, что вы имеете в виду. Не могли бы вы привести пример кода? – fxfuture

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