15

ねえSOGuruのimはこのコードで1つの仕事をしています

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());
}

プログラムを初めて実行しようとすると、このエラーが発生します。

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)

少しゴーグルしたので、これはスレッドで通常発生するエラーのようです。スレッドが同じリソースに同時にアクセスしようとする理由ですが、これが、このシステムでマルチスレッド化をまったく行わない理由です。

誰かがこれが起こっている理由を説明できますか、それを回避するためのハックを考えてください

どうもありがとう^_^

4

4 に答える 4

41

(ループに隠されている)の基Collectionになる部分を変更できます。これを行う適切な方法は次のとおりです。Iteratorfor-each

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();
    }
}
于 2009-11-29T17:56:14.763 に答える
12

for eachコレクションから物を削除すると、ループを使用できなくなります。
とを使用してIterator、現在のアイテム呼び出しを削除する必要がありますIterator.remove

そうしないと、for-eachループが舞台裏で作成する基本的なイテレーターは、コレクションがどのように変更されているのかを理解せず、反復中にコレクションが変更されていることを通知します。

于 2009-11-29T17:53:43.673 に答える
8

forループの下に隠された人口に対するイテレータがあります。イテレータが機能している最中に、母集団からアイテムを削除しています。イテレータの途中でコレクションを変更したため、イテレータは機能しなくなりました。

マルチスレッドとは関係ありません。

于 2009-11-29T17:54:31.977 に答える
4

回避策は、コレクションをコピーすることです。コピーを繰り返し処理し、元のコレクションから要素を削除します。

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());

}

于 2010-11-26T18:10:46.130 に答える