2012-09-13 43 views
2

我想設計一個轉換的流程圖爲Java或任何其他代碼的軟件。然而,我一再得到ConcurrentModificationException .. 但我不能使用布爾值來防止concurrentModification,因爲訪問鏈表發生在各個地方。ConcurrentModificationException的在LinkedList的

因此,作爲一個解決方案,我創建了以下適配器類。但是它也會從下一個方法拋出相同的異常。是否有任何其他的解決方案,或者如果可以,PLZ讓我知道如何修改我的代碼...

非常感謝你......

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必須是對SO有史以來最有幫助的評論「一旦你解決這個問題,將工作」。 – josefx

+1

@josefx:我的觀點是他的問題是完全向後解決問題。 – SLaks

+0

是的。這是正確的。在設計軟件時,我並沒有預料到任何多線程問題,因爲我使用了單線程。但是,使用paintComponent時會出現意外的多線程問題。然後作爲解決方案,我嘗試使用適配器。非常感謝 – maamaa

回答

7

通過列表迭代時,ConcurrentModificationException通常拋出同時通常是另一個線程或甚至同一個循環嘗試修改(添加/刪除)列表的內容。

+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

不幸的是,這是行不通的。我試圖用兩個同步的(列表)兩個定時器修改列表。 – Colateral

0

這種情況發生時,你遍歷列表和循環主體元素添加到它。當您使用迭代器的remove()方法時,您可以安全地移除元素,但不能通過調用列表本身的任何remove()方法。

解決的辦法是複製列表中你迭代它之前:

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

Java集合是快速失敗的,這意味着所有現有的迭代器在底層集合被修改時變爲無效 - 同步修改並不會阻止列表使所有迭代器無效。

作爲一種變通方法,您可以創建列表的副本來遍歷或直到迭代完成推遲修改。要刪除條目,您還可以使用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. 

注:如果您使用的是隊列,另一個線程我建議你使用ExecutorService的,因爲這結合了排隊的線程池,並與「後臺」線程的工作容易得多。

0

答案在這裏:Why am I getting java.util.ConcurrentModificationException?幫了我很多。

我會複製並在情況下,有人在這裏貼正在修復此錯誤:

當你遍歷List,你不能從中刪除項目。這樣做會導致異常。

務必:

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