在以下情况下,我收到一个ConcurrentModificationException错误。线 发生这种情况的地方标记为“ <-------- ConcurrentModificationException”
我有一个从列表中读取的主线程,如下所示:
List<ThemeCacheIndex> list = Collections.synchronizedList(themeCacheList);
synchronized (list) {
Iterator<ThemeCacheIndex> it = list.iterator();
while (it.hasNext()) {
ThemeCacheIndex themeCacheIndex = it.next(); <-------- ConcurrentModificationException
doSomething();
}
}
我有一个AsyncTask将从此列表中删除:
@Override
protected String doInBackground(String... params) {
someElementsToRemove = calculateWhichElementsToRemove();
for(int i=0 ; i < someElementsToRemove.size() ; i++){
themeCacheList.remove(someElementsToRemove.get(i));
}
}
我可以想象,这涉及到并发情况,但是我想通过在主线程上使用同步列表来阻止这种情况。
似乎我不了解多线程和共享对象的概念。
有人可以帮助我解决这个问题吗?如何防止这种冲突?
答案 0 :(得分:1)
引用Collections
Javadoc:
返回由指定对象支持的同步(线程安全)列表 清单。为了保证串行访问,至关重要的是所有 通过返回的列表可以访问后备列表。
如果您的AsyncTask
修改了themeCacheList
,则同步操作将无济于事,因为后备列表被修改了。
答案 1 :(得分:0)
AsyncTask代码很好。对“主”线程代码执行此操作:
synchronized (themeCacheList) {
Iterator<ThemeCacheIndex> it = themeCacheList.iterator();
while (it.hasNext()) {
ThemeCacheIndex themeCacheIndex = it.next();
doSomething();
}
}
如您所见,我已经删除了Collections.synchronizedList
,因为它是多余的,我直接在themeCacheList
上进行了同步。
答案 2 :(得分:0)
不确定我有一个好的解决方案,但是我想这两个示例可以说明问题和可能的解决方案。 “可能重复”答案没有显示任何解决方案,而只是在说明问题所在。
@Test
public void testFails(){
List<String> arr = new ArrayList<String>();
arr.add("I");
arr.add("hate");
arr.add("the");
arr.add("ConcurrentModificationException !");
Iterator i = arr.iterator();
arr.remove(2);
while(i.hasNext()){
System.out.println(i.next());
}
}
@Test
public void testWorks(){
List<String> arr = new CopyOnWriteArrayList<>();
arr.add("I");
arr.add("hate");
arr.add("the");
arr.add("ConcurrentModificationException !");
Iterator i = arr.iterator();
arr.remove(2);
while(i.hasNext()){
System.out.println(i.next());
}
}