为什么我使用同步列表并仍然得到 ConcurrentModificationException
Why i used synchronized list and still get ConcurrentModificationException
我在 I used synchronized list, and i still get ConcurrentModificationException 中找到了同样的问题,但没有找到正确答案。
这是我定义 synchronized
列表的方式:
private List<ActionItemClickListener> actionItemClickListeners = Collections.synchronizedList(new ArrayList<ActionItemClickListener>());
下面是我的使用方式:
@Override
public void onBackPressed() {
boolean isConsume = false;
synchronized (actionItemClickListeners) {
//ConcurrentModificationException occur here
for (ActionItemClickListener listener : actionItemClickListeners) {
isConsume = isConsume | listener.onSystemBackPressed();
}
}
if(!isConsume) {
pendingFragment = null;
pendingTag = null;
currentFragmentTag = null;
super.onBackPressed();
}
}
public void addActionItemClickListener(ActionItemClickListener listener) {
synchronized (actionItemClickListeners) {
if (listener != null)
actionItemClickListeners.add(listener);
}
}
public void removeActionItemClickListener(ActionItemClickListener listener) {
synchronized (actionItemClickListeners) {
if (listener != null)
actionItemClickListeners.remove(listener);
}
}
为什么我仍然收到 ConcurrentModificationException
???
您的 ConcurrentModificationException
不是线程问题。抛出它是因为您在迭代列表时正在修改列表。
for (ActionItemClickListener listener : actionItemClickListeners) {
isConsume = isConsume | listener.onSystemBackPressed();
}
问题是 listener.onSystemBackPressed();
正在调用 removeActionItemClickListener
,它试图更改您正在迭代的 actionItemClickListeners
。尝试更改您正在迭代的列表将导致 ConcurrentModificationException
如何修复
没有看到你的其余代码,我只能猜测如何解决这个问题,但你可以使用 iterator.next()
、iterator.hasNext()
和 iterator.remove()
循环和删除听众,分别。你要么需要通过 onSystemBackPressed()
和 removeActionItemClickListener
传递 iterator
,这有点难看,要么让 onSystemBackPressed()
return 一个布尔值指示它是否应该删除侦听器。
final Iterator<String> iterator = actionItemClickListeners.iterator();
while (iterator.hasNext()) {
final String listener = iterator.next();
final boolean removeListener = listener.onSystemBackPressed();
if (removeListener) {
iterator.remove();
}
isConsume = isConsume | removeListener;
}
不幸的是,您似乎将 onSystemBackPressed()
的 return 值用于其他用途,因此这可能也不起作用。
我在 I used synchronized list, and i still get ConcurrentModificationException 中找到了同样的问题,但没有找到正确答案。
这是我定义 synchronized
列表的方式:
private List<ActionItemClickListener> actionItemClickListeners = Collections.synchronizedList(new ArrayList<ActionItemClickListener>());
下面是我的使用方式:
@Override
public void onBackPressed() {
boolean isConsume = false;
synchronized (actionItemClickListeners) {
//ConcurrentModificationException occur here
for (ActionItemClickListener listener : actionItemClickListeners) {
isConsume = isConsume | listener.onSystemBackPressed();
}
}
if(!isConsume) {
pendingFragment = null;
pendingTag = null;
currentFragmentTag = null;
super.onBackPressed();
}
}
public void addActionItemClickListener(ActionItemClickListener listener) {
synchronized (actionItemClickListeners) {
if (listener != null)
actionItemClickListeners.add(listener);
}
}
public void removeActionItemClickListener(ActionItemClickListener listener) {
synchronized (actionItemClickListeners) {
if (listener != null)
actionItemClickListeners.remove(listener);
}
}
为什么我仍然收到 ConcurrentModificationException
???
您的 ConcurrentModificationException
不是线程问题。抛出它是因为您在迭代列表时正在修改列表。
for (ActionItemClickListener listener : actionItemClickListeners) {
isConsume = isConsume | listener.onSystemBackPressed();
}
问题是 listener.onSystemBackPressed();
正在调用 removeActionItemClickListener
,它试图更改您正在迭代的 actionItemClickListeners
。尝试更改您正在迭代的列表将导致 ConcurrentModificationException
如何修复
没有看到你的其余代码,我只能猜测如何解决这个问题,但你可以使用 iterator.next()
、iterator.hasNext()
和 iterator.remove()
循环和删除听众,分别。你要么需要通过 onSystemBackPressed()
和 removeActionItemClickListener
传递 iterator
,这有点难看,要么让 onSystemBackPressed()
return 一个布尔值指示它是否应该删除侦听器。
final Iterator<String> iterator = actionItemClickListeners.iterator();
while (iterator.hasNext()) {
final String listener = iterator.next();
final boolean removeListener = listener.onSystemBackPressed();
if (removeListener) {
iterator.remove();
}
isConsume = isConsume | removeListener;
}
不幸的是,您似乎将 onSystemBackPressed()
的 return 值用于其他用途,因此这可能也不起作用。