2009-11-29 6 views
15

헤이 SO이 코드 내 프로그램이 코드를 실행하려고 처음 실행java.util.ConcurrentModificationException 프로그램

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) 

이 일반적으로 그들이 시도 동시에 같은 리소스에 액세스하는 이유 스레드 발생하는 오류 것으로 보인다 조금 주위를 이리저리 굴리는 데,하지만 날이 시스템에서 모든 멀티 스레딩하지 메신저 얻는 것입니다.

누군가는 이런 일이 이유를 설명하거나 주위에

많은 감사를 얻기 위해 해킹 생각할 수^_^

답변

41

Iterator (for-each 루프에 숨겨져 있음)의 기본 Collection을 수정할 수 있습니다. 이 작업을 수행하는 적절한 방법은 다음과 같습니다

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

감사합니다. 내 코드가 작동하는 큰 덩어리가 있습니다. – Gwilym

12

당신이 컬렉션에서 일을 제거하면 당신은 for each 루프를 사용할 수 없습니다.
Iterator을 사용하고 현재 항목 호출 Iterator.remove을 제거해야합니다.

그렇지 않으면 for-each 루프가 배경을 위해 생성하는 반복기는 반복되는 컬렉션이 어떻게 바뀌는 지 이해하지 못한다. 반복하는 동안 변경되는 것을 알 수있다.

+0

덕분에이 http://java.sun.com/javase/6/docs/api/java/util/ 당 (sence – Gwilym

+0

반복자의 그나마 많이 반드시이 방법을 구현해야한다 Iterator.html # remove % 28 % 29). –

+0

@ Kaleb -이 경우 반복하는 동안 물건을 제거하면 안됩니다. – abyx

8

for 루프 아래에 숨겨진 채우기에 대한 반복기가 있습니다. 반복자 작업 중간에 항목을 제거하고 있습니다. 반복 도중에 컬렉션을 변경했기 때문에 반복자가 더 이상 작동하지 않습니다.

멀티 스레딩과 관련이 없습니다.

+0

많은 감사합니다. aswell – Gwilym

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

}

+2

어떤 이유로 든 iterator.remove()를 쉽게 호출 할 수 없을 때 작동합니다. –