为什么我使用同步列表仍然得到ConcurrentModificationException

时间:2015-05-16 12:08:41

标签: java android concurrency thread-safety

我在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 ???

1 个答案:

答案 0 :(得分:2)

您的ConcurrentModificationException不是线程问题。抛出它是因为您在迭代时修改列表。

for (ActionItemClickListener listener : actionItemClickListeners) {
    isConsume = isConsume | listener.onSystemBackPressed();
}

问题是listener.onSystemBackPressed();正在调用removeActionItemClickListener,它会尝试更改您正在迭代过程中的actionItemClickListeners。尝试更改您正在迭代的列表将导致ConcurrentModificationException

如何修复

在没有看到其余代码的情况下,我只能猜测如何解决此问题,但您可以使用iterator.next()iterator.hasNext()iterator.remove()来循环并删除听众,分别。您需要传递iteratoronSystemBackPressed()removeActionItemClickListener,这有点难看,或者onSystemBackPressed()返回一个布尔值,指示是否应该删除侦听器。

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()的返回值来表示其他内容,因此也可能无效。