2009-11-29 4 views
15

Hey SO bu kodu benim program kod yürütmeye çalışırsa ilk kez çalıştırmakjava.util.ConcurrentModificationException Programı

public void kill(double GrowthRate, int Death) 
{ 
    int before = population.size(); 
    for (PopulationMember p : population) 
    { 
     int[] probs = ProbablityArrayDeath(GrowthRate,Death,(int)p.fitness()); 
     if (probs[RandomNumberGen.nextRandomInt(0, 99)]==0) 
     { 
      population.remove(p); 
     } 
    } 
    System.out.println("Intial Population: "+before+", Deaths:"+(before-   population.size())+", New Population: "+population.size()); 
} 

bir iş çıkardılar sahip Guru'nun im bu hatayı vurur

Exception in thread "main" java.util.ConcurrentModificationException 
    at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793) 
    at java.util.HashMap$KeyIterator.next(HashMap.java:828) 
    at Genetics.Population.kill(Population.java:181) 
    at Genetics.Population.run(Population.java:47) 
    at Control.Main.main(Main.java:35) 

bu normalde onlar denemek ve eş zamanlı olarak aynı kaynağa erişmek neden parçacığı ile gerçekleşen bir hata gibi görünüyor biraz etrafına fal olması, ama bu beni bu sistemde hiç mulithread değil im alma şeydir.

birisi bu neden oluyor açıklamak veya çevresine

çok teşekkür ederiz almak için bir hack düşünebiliyor^_^

cevap

41

Iterator'un (for-each döngüsünde gizlenen) Collection temelini değiştirebilirsiniz. Bunu yapmanın doğru yoludur:

for (Iterator<PopulationMember> it = population.iterator(); it.hasNext();) { 
    PopulationMemeber p = it.next(); 
    int[] probs = ProbablityArrayDeath(GrowthRate,Death,(int)p.fitness()); 
    if (probs[RandomNumberGen.nextRandomInt(0, 99)] == 0) { 
     it.remove(); 
    } 
} 
+0

teşekkürler bu benim kod çalışmamın büyük bir yığın var – Gwilym

12

koleksiyondan şeyler kaldırırsanız for each döngü kullanamazsınız.
Iterator numaralı telefonu kullanmanız ve mevcut ürün aramayı Iterator.remove kaldırmak zorundasınız.

Aksi takdirde, her bir döngü için sahnelerin ardında sizin için oluşturduğu temel yineleyici, içinden geçmekte olduğu koleksiyonun nasıl değiştiğini anlamıyor, yinelediğinizde değiştirildiğini söyler.

+0

sayesinde bu http://java.sun.com/javase/6/docs/api/java/util/ başına (sence – Gwilym

+0

yineleyici en dont sürü mutlaka bu yöntemi uygulamak zorunda yapar Iterator.html # remove% 28% 29). –

+0

@Kaleb - bu durumda iterasyon sırasında hiç bir şeyleri kaldırmamalı. – abyx

8

For döngüsü altında gizli popülasyon üzerinde yineleyici var. Yineleyici çalışmanın ortasında bulunan bir öğeden bir öğeyi kaldırıyorsunuz. Yineleyici artık çalışamaz çünkü koleksiyonun ortasında yinelenen değişiklikler siz değişti.

Bu, çoklu okuma ile ilgili değildir.

+0

çok teşekkürler, teşekkürler – Gwilym

4

ilişkin bir çözüm, koleksiyon kopyalamak olabilir. Kopyayı yineleyin ve orijinal koleksiyondan öğeleri kaldırın.

public void kill(double GrowthRate, int Death) { 
    int before = population.size(); 
    Collection<PopulationMember> forIteration = new HashSet<PopulationMember>(population); 
    for (PopulationMember p : forIteration) { 
     int[] probs = ProbablityArrayDeath(GrowthRate,Death,(int)p.fitness()); 
     if (probs[RandomNumberGen.nextRandomInt(0, 99)]==0) { 
      population.remove(p); 
     } 
    } 
    System.out.println("Intial Population: "+before+", Deaths:"+(before - population.size())+", New Population: "+population.size()); 

}

+2

Herhangi bir nedenle iterator.remove() kolayca arayamıyorum zaman bu çalışır. –