2016-09-14 4 views
3

Main 메서드 내에서 for 루프를 입력하는 코드가 있습니다.java.util.ConcurrentModificationException의 원인을 찾을 수 없습니다.

for (List<Point2D> points : output) { 
    currentPath = pathDistance(points); 
    if (shortest == 0){ 
     shortest = currentPath; 
    } else if (currentPath < shortest) { 
     best = points; 
     shortest = currentPath; 
    } 
} 
pathDistance

public static Double pathDistance(List<Point2D> path){ 
    double distance = 0; 
    int count = path.size()-1; 

    for (int i = 0; i < count; i++) { 
     distance = distance + path.get(i).distance(path.get(i+1)); 
    } 

    distance = distance + path.get(0).distance(path.get(count)); 
    return distance; 
} 

으로 정의된다

하지만 오류

가 계속
Exception in thread "main" java.util.ConcurrentModificationException 
    at java.util.SubList.checkForComodification(Unknown Source) 
    at java.util.SubList.size(Unknown Source) 
    at java.util.Collections$SynchronizedCollection.size(Unknown Source) 
    at TSMain.pathDistance(TSMain.java:76) 
    at TSMain.main(TSMain.java:203) 

나는 이것이 반복에 의존하는 동안 객체를 변경하고 있음을 뜻 알고 하지만 그 삶은 어디에서 일어날 지 알 수 없습니다. 어떤 도움을 주시면 감사하겠습니다.

+2

당신은 '출력'을 변경하고 있지만, 반드시이 'for' 루프에있는 것은 아닙니다. 이것은 또 다른 코드의 다른 쓰레드에 의해 행해질 수도 있지만,'output' 객체와 완전히 똑같은 참조를 가지고 있습니다. – Tom

+0

개선 된 for 루프를 각 반복에서 크기를 계산하는 전통적인 방법으로 대체하십시오. 목록을 전혀 수정하지 않고 (요소를 제거하거나 요소를 추가하는 경우) 향상된 for 루프에서 문제가 발생합니다. –

+2

'Collections.synchronizedCollection'에 의해 싸여진 sublist를 전달하는 것처럼 보입니다. 그러나 원래 목록은 반복되는 동안 수정됩니다. – vsminkov

답변

1

스택 트레이스는 코드 subList의 어딘가가 (직접 또는 간접적으로) Collections.synchronizedCollection에게 전달되었음을 보여줍니다. 이처럼

Set<List<Point2D>> output = Collections.singleton(
    Collections.synchronizedCollection(data.subList(start, end))); 

그러나 data 목록을 복사하지 않습니다. 그리고 points subList는 여전히 data 목록의 범위를 가리 킵니다. 그리고 원래 목록은 momet에서 수정됩니다 path.size() 전화가 발생합니다.

쉽게 나는 또한 코드의 동기화에 문제가있는 것 같습니다 통지해야 pathDistance

for(List<Point2D> points : output){ 
    List<Point2D> pointsCopy = new ArrayList<>(points) 
    currentPath = pathDistance(pointsCopy); 
    // rest of code using pointsCopy 
} 

에 전달하기 전에 명시 적 목록 사본을 수행하여 문제를 해결할 수 있습니다. 동기화 된 컬렉션에서 하위 목록을 배치하는 것은 나쁜 생각입니다. 원래 목록이 적절한 동기화없이 안전하지 않은 방법으로 수정 될 수 있기 때문입니다.

AbstractList#modCount 소스를 살펴보면 목록 수정 확인에 대해 자세히 알아볼 수 있습니다.

관련 문제