【问题标题】:Why i used synchronized list and still get ConcurrentModificationException [duplicate]为什么我使用同步列表仍然得到 ConcurrentModificationException [重复]
【发布时间】:2015-05-16 12:08:41
【问题描述】:

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

【问题讨论】:

  • 你能告诉我们你从哪里得到异常吗?另外,super.onBackPressed(); 是什么?
  • @ReutSharabani,是一个android回调,当按下返回按钮时由操作系统调用
  • @ReutSharabani 我在代码中评论,super.onBackPressed() 是一个超级调用,我的类扩展自 Activity 类。
  • @mr.icetea 您是否尝试了常规的for 循环? stackoverflow.com/questions/2397321/…
  • @ReutSharabani 看起来不错,我会试试的。感谢您的建议!

标签: java android concurrency thread-safety


【解决方案1】:

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

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

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

如何解决

没有看到您的其余代码,我只能猜测如何解决此问题,但您可以使用iterator.next()iterator.hasNext()iterator.remove() 分别循环和删除侦听器。您要么需要通过onSystemBackPressed()removeActionItemClickListener 传递iterator,这有点难看,要么让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() 的返回值用于其他用途,因此这也可能不起作用。

【讨论】:

  • 感谢您的解释。你能帮我为我的案子找到解决方案吗?
  • @mr.icetea 添加了可能的解决方案来回答。但是,如果没有更多细节,很难说它是否会有所帮助。在任何情况下,您都可以像上面一样使用Iterator 在迭代列表时从列表中删除,这样有望帮助您找到解决方案。
猜你喜欢
  • 2013-03-04
  • 1970-01-01
  • 2019-12-27
  • 2014-06-19
  • 2014-09-26
  • 1970-01-01
  • 2015-02-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多