2012-09-13 4 views
2

코드를 Java 또는 다른 코드로 변환하는 소프트웨어를 설계하려고합니다. 그러나 반복적으로 ConcurrentModificationException을 받고 .. 하지만 연결된 목록에 대한 액세스가 여러 위치에서 발생하기 때문에 부울을 사용하여 concurrentModification을 방지 할 수는 없습니다.LinkedList의 ConcurrentModificationException

그래서 해결책으로 아래 어댑터 클래스를 만들었습니다. 그러나 다음 메소드에서도 같은 예외가 발생합니다. ...

가 대단히 감사합니다 ... 목록을 반복 할 때 ConcurrentModificationException는 일반적으로 발생합니다

import java.util.Iterator; 
import java.util.LinkedList; 

public class LinkedListAdapter<T> extends LinkedList<T>{ 

@Override 
public boolean add(T t){ 

    boolean b; 

    synchronized(this){ 
     b = super.add(t); 
    } 

    return b; 
} 

@Override 
public T remove(){ 

    T t; 

    synchronized(this){ 
     t = super.remove(); 
    } 

    return t; 
} 

@Override 
public Iterator<T> iterator(){ 

    final LinkedListAdapter<T> adap = this; 

    return 
     new Iterator<T>(){ 

     private Iterator<T> iter; 

     { 
      synchronized(adap){ 
       iter = LinkedListAdapter.this.getIterator(); 
      } 
     } 

     @Override 
     public boolean hasNext() { 

      boolean b; 

      synchronized(adap){ 
       b = iter.hasNext(); 
      } 

      return b; 
     } 

     @Override 
     public T next() { 

      T t; 

      synchronized(adap){ 
       t = iter.next(); 
      } 

      return t; 
     } 

     @Override 
     public void remove() { 
      throw new UnsupportedOperationException(); 
     } 
    }; 
} 

protected Iterator<T> getIterator() { 

    Iterator<T> iter; 

    synchronized(this){ 
     iter = super.iterator(); 
    } 

    return iter; 
} 
} 
+2

@SLaks는 "당신이 해결되면 작동됩니다." – josefx

+1

@josefx : 요점은 그의 질문이 문제를 완전히 거꾸로 다루는 것입니다. – SLaks

+0

예. 맞습니다. 내가 단일 스레드를 사용했기 때문에 소프트웨어를 설계 할 때 어떤 멀티 스레딩 문제도 예상하지 못했습니다. 그러나 paintComponent를 사용할 때 멀티 스레딩 문제가 예기치 않게 발생합니다. 그런 다음 해결책으로 어댑터를 사용하려고했습니다. 고맙습니다. – maamaa

답변

7

을 다른 솔루션이 있습니까 또는 수 있다면, PLZ 내 코드를 수정하는 방법을 알려 같은 시간에 다른 스레드 또는 동일한 루프가 목록의 내용을 수정 (추가/제거)하려고합니다.

+0

예, 제 프로그램에서는 두 스레드가 동시에 반복되지만 코딩은 다른 위치에 있습니다. 왜냐하면 나는 어댑터를 만들려고했기 때문입니다. 대단히 감사합니다 .... – maamaa

+0

어떻게 목록에서 항목을 검색하여 제거하고 제거 할 수 있습니까? –

0
List<X> myList = .... 
List<X> myThreadSafeList = synchronizedList(myList); 

synchronizedList(myList)

공지 사항 JavaDoc을에 다음 문 : 당신이 목록을 반복 루프의 몸에에 요소를 추가 할 때

It is imperative that the user manually synchronize on the returned list when iterating over it:

List list = Collections.synchronizedList(new ArrayList()); 
    ... 
synchronized(list) { 
    Iterator i = list.iterator(); // Must be in synchronized block 
    while (i.hasNext()) 
     foo(i.next()); 
} 
+0

불행히도 이것은 작동하지 않습니다. 나는 둘 다에 동기화 (목록)와 함께 2 타이머에서 목록을 수정하려고했습니다. – Colateral

0

발생합니다. 반복자의 remove() 메서드를 사용할 때는 요소를 안전하게 제거 할 수 있지만 목록 자체의 remove() 메서드는 호출하지 말고 안전하게 요소를 제거 할 수 있습니다.

List<T> copy = new ArrayList<T>(list); 
for(T e : copy) { 
    ... you can now modify "list" safely ... 
} 
2

은 왜 안 에 LinkedBlockingQueue를 사용 : 당신이 그것을 반복하기 전에

해결책은 목록을 복사하는 것입니다? http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/LinkedBlockingQueue.html

아직, 반드시 동기화와 관련이 있습니다. 다음과 같은 코드 :

for(Value v : valuesList){ 
    valueslist.add(new Value()); 
} 

이 예외의 원인이됩니다. 반복 될 때 목록의 가능한 수정 코드를 확인하십시오.

1

Java 콜렉션은 fail-fast입니다. 즉, 기본 콜렉션이 수정 될 때 기존의 모든 반복자가 유효하지 않게됩니다. 즉, 수정 사항을 동기화해도 목록의 모든 반복자가 무효화되지 않습니다.

임시 해결 방법은 반복 실행이 완료 될 때까지 수정 사항을 반복 또는 연기하기 위해 목록 사본을 만들 수 있습니다. 항목을 제거하려면 반복기 자체를 유효하게 유지하는 iterator.remove() 메소드를 사용할 수도 있습니다.

2

synchronizedList 또는 동기화 된 목록을 사용하면 반복 할 때 외부에서 동기화해야합니다.

ConcurrentLinkedQueue를 사용하는 경우 이러한 문제가 없습니다.

Queue<Task> tasks = new ConcurrentLinkedQueue<Task>(); 
tasks.add(task); // thread safe 
tasks.remove(task2); // thread safe 

for(Task t: tasks) // can iterate without a CME. 

참고 : 다른 스레드와 큐를 사용하는 경우 I는이 스레드 풀과 대기열을 결합하여 훨씬 쉽게 "배경"스레드로 작업 할 당신이 ExecutorService를를 사용하는 것이 좋습니다.

0

답변은 여기 Why am I getting java.util.ConcurrentModificationException? 나를 많이 도왔습니다. 당신이 목록을 반복하면

, 당신은 그것에서 항목을 제거 할 수 없습니다 :

내가 복사의 경우 사람이 여기에 붙여 넣기합니다

이 오류를 해결하기 위해 찾고 있습니다. 그렇게하면 예외가 발생합니다.

해야 할 것 : SO 이제까지 가장 유용한 코멘트 수있다

int size = list.size(); 
for (int i = 0 ; i< size ; i++) { 
    list.add(0,"art"); 
    list.remove(6); 
    System.out.println(list); 
}