2014-11-20 9 views
3

아래의 재귀 함수는 'continue'문에서 ConcurrentModificationException을 발생시킵니다. ConcurrentModificationException에 대한 몇 가지 게시물을 살펴본 결과 모든 요소는 요소에서 요소를 제거하는 것으로 보였지만 내 함수의 요소는 제거하지 않는 것 같습니다.java.util.ConcurrentModificationException 그러나 제거하지 않습니다.

내 기능은 다음과 같습니다 : 요청으로

public static void getRootedTreeHelper(Node n, boolean[] marked, String spacing){ 

     System.out.println(spacing + "in helper with " + n.getId()); 
     marked[n.getId()] = true; 
     if(n.children.isEmpty()) 
      return; 
     else{ 
      for(Node child : n.children){ 
       if(marked[child.getId()]) 
        continue; // ConcurrentModificationException is thrown here. 
       else{ 
        n.addChild(child); 
        spacing = spacing + "\t"; 
        getRootedTreeHelper(child, marked, spacing); 
       } 
      } 
     } 
    } 

가 : 노드 클래스의 관련 부분은 가

public class Node { 

    private int id; 
    ArrayList<Node> children; 

    public Node(int id) { 
     this.id = id; 
     children = new ArrayList<Node>(); 
    } 

    /** 
    * add node n to this node's children 
    * @param n 
    */ 
    public void addChild(Node n) { 
     children.add(n); 
    } 

    // getters and setters() 
    public int getId() { 
     return id; 
    } 
    public void setId(int id) { 
     this.id = id; 
    } 
} 

사람이 어떤 아이디어가 있습니까

다음과 같습니다?

편집 해결 : 각 루프마다 for를 사용하여 모든 자식을 반복하는 대신 for 루프를 사용합니다. ConcurrentModificationException 자바 독에서

+0

노드 클래스 표시 – Venkatesh

+0

n.children은 어떤 유형입니까? stacktrace를 추가 할 수 있습니까? – flob

+4

같은 'ConcurrentModificationException'은 반복하는 동안 목록에 추가 할 때도 발생할 수 있습니다. –

답변

2

:이 예외가 항상하지 않는 것을

주 객체가 동시에 다른 스레드에 의해 수정되었음을 나타냅니다. (...)
의 경우, 스레드가 패스트 패스트 반복자를 사용하여 컬렉션에 대해
반복을 반복하는 동안 컬렉션을 직접 수정하면 반복자 이이 예외를 throw합니다.

버그는 컬렉션을 반복하면서 그 컬렉션에 자식을 추가하는 중입니다.

루프는 for 루프에서 증가 될 때 반복기에 의해 이 발견되어이 발견되었습니다.

+0

이 경우입니다. 문제는 그가 자신의 초보적인'Node' 클래스를 만들었 기 때문에 그는이 기능을 가지고 있지 않다는 것입니다. – hfontanez

+0

이것은 반복하는 동안 [실패한] 재진입 액세스로 인해 발생할 수 있습니다. 스레드가 필요하지 않습니다. – user2864740

4

ArrayList의 Iterator 구현을 살펴보면 Iterator.next() 동안 컬렉션의 크기가 변경되었는지 확인합니다.

if (i >= elementData.length) 
    throw new ConcurrentModificationException(); 

심지어는 여전히 같은 Iterator를 사용하기 때문에 도움이되지 것 Collections.synchronizedList(n.children)와 동기화 된 버전을 사용.
  • ConcurrentLinkedQueue 또는 ConcurrentLinkedDeque 등의 동시 변경을 허용하는 버전을 사용, 현재의 요소를 제거하기 위해

    • 사용 Iterator.remove() :

      그래서 당신이 컬렉션을 수정 동시 액세스해야하는 경우 몇 가지 선택 사항이 있습니다 또는

    • 변경 사항을 반복하는 것보다 쓰기 위해 또 다른 List을 사용하십시오.

    당신이 시도 할 수있는 LinkedList - 내가 완전히 소스를 읽지 않은 있지만 반복하는 동안 추가로 면역처럼 그 Iterator에 잠깐 한 눈에 보인다.

  • 관련 문제