2015-05-05 37 views
0

我有下面的代碼在後臺線程ConcurrentModificationException的在iterator.next()

private List<IStartAction> mActions = Collections.synchronizedList(new ArrayList<IStartAction>()); 

protected void removeNonApplicableActions() { 
     Iterator<IStartAction> iterator = mActions.iterator(); 
     while (iterator.hasNext()) { 
      IStartAction action = iterator.next(); 
      if (!action.isApplicable()) { 
       iterator.remove(); 
      } 
     } 
    } 

當我運行這個在主線程獲得ConcurrentModificationException的成iterator.next()。 這是怎麼回事?我使用線程安全的集合並通過迭代器移除項目。僅用於此線程的集合。

+0

synchronized表示您可以在特定條件下修改多個線程中的列表(請參閱javadoc for synchronizedList()方法)。這是一個不同的問題,你正在同時迭代和刪除。請使用listIterator而不是普通的迭代器。使用listIterator()方法。 – Tomek

+3

你能提供一個你的代碼的最小工作例子,以便我們能夠重現問題嗎? –

+2

'ConcurrentModificationException'並不是_必須_表示您有多個線程正在修改您的列表,而是您正在同時遍歷列表並同時修改它。 –

回答

2

同步集合的線程安全性僅適用於一個方法調用。在方法調用之間,鎖被釋放,另一個線程可以鎖定集合。如果你執行兩個操作,在此期間可能發生任何事情,除非你鎖定了你的自我。例如

// to add two elements in a row, you must hold the lock. 
synchronized(mAction) { 
    mAction.add(x); 
    // without holding the lock, anything could happen in between 
    mAction.add(y); 
} 

與迭代同步集合類似,您必須保持鎖定,否則可能會在迭代器的方法調用之間發生任何事情。

synchronized (mAction) { 
    for(Iterator<IStartAction> iter = mActions.iterator(); iter.hashNext();) { 
     IStartAction action = iter.next(); 
     if (!action.isApplicable()) { 
      iter.remove(); 
     } 
    } 
} 
相關問題