当前位置: 首页 > 知识库问答 >
问题:

引发ConcurrentModificationException的ArrayList迭代器

段志
2023-03-14
private final List<WeakReference<LockListener>> listeners = new ArrayList<>();

所有订阅操作都使用以下内容:

public void subscribe(@NonNull LockListener listener) {
    for (Iterator<WeakReference<LockListener>> it = listeners.iterator(); it.hasNext(); ) {
        // has this one already subscribed?
        if (listener.equals(it.next().get())) {
            return;
        }
    }
    listeners.add(new WeakReference<>(listener));
}

所有取消订阅操作都使用以下内容:

public void unsubscribe(@NonNull LockListener listener) {
    if (listeners.isEmpty()) {
        return;
    }

    for (Iterator<WeakReference<LockListener>> it = listeners.iterator(); it.hasNext(); ) {
        WeakReference<LockListener> ref = it.next();
        if (ref == null || ref.get() == null || listener.equals(ref.get())) {
            it.remove();
        }
    }
}

和通知者:

private void notifyListeners() {
    if (listeners.isEmpty()) {
        return;
    }

    Iterator<WeakReference<LockListener>> it = listeners.iterator();
    while (it.hasNext()) {
        WeakReference<LockListener> ref = it.next();
        if (ref == null || ref.get() == null) {
            it.remove();
        } else {
            ref.get().onLocked();
        }
    }
}

共有1个答案

衡安晏
2023-03-14

如果我正确地读到了您的最后一句话,那么您的示例中的三个方法是从几个线程并发调用的。如果情况确实如此,那么这就是你的问题。

ArrayList不是线程安全的。在没有附加同步的情况下并发地修改它会导致未定义的行为,无论您是直接修改它还是使用迭代器。

您可以同步对列表的访问(例如,使三个方法同步),或者使用线程安全的集合类,如ConcurrentLinkedDeque。如果是后者,请确保阅读JavaDoc(特别是关于迭代器每周一致的部分),以了解哪些是保证的,哪些是不保证的。

 类似资料:
  • 问题内容: 我下面有以下代码 现在我正在使用一个Android游戏,并且上面的代码以多线程方式运行。现在我有一个例外。我已经研究了如何解决问题,但似乎对我没有帮助。我在上面的代码上所做的是 随机删除一个条目 。我如何在那里实现它? 问题答案: 除非使用,否则不能在迭代时从集合中删除元素。 这就是导致异常的原因。 使用Iterator#remove()在遍历集合时删除元素,例如 编辑 :(响应OP的

  • 问题内容: 我有以下代码: 当我尝试运行它时,我得到了,即使代码在同一线程中运行,没有人能解释为什么会发生吗?我该如何避免呢? 问题答案: 如果使用循环浏览列表,则无法从列表中删除。你可以使用。更换: 带有:

  • 问题陈述:为以下场景设计系统: 1.物料列表包含多个物料的物料编码、名称、费率和数量。 每当在列表中添加新项目时,都要检查项目编码的唯一性。用新产品的价格注册一个新产品。 项目的时间比率可能会更改。 每当发出或接收一个项目时,检查该项目的存在性并更新数量。 出库时,还要检查数量的可用性。 用户可能还想知道一个项目的价格/数量。 查找多少项目的成本超过给定金额。金额将是一个参数。 请记住,如果给出了

  • 问题内容: 为什么这段代码不抛出?它在不使用方法的情况下修改了一段时间,这是唯一安全的删除方法。 如果将替换为,则会得到相同的结果。但是,如果我将列表更改为或只是得到了预期的异常。到底是怎么回事?我正在使用是否相关。 编辑 我找到了以下链接 http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4902078 相关部分是 天真的解决方案是将协同修改

  • 问题内容: 当我运行此代码时,我将抛出ConcurrentModificationException。 当我从列表中删除指定的元素时,列表似乎不知道其大小已更改。 我想知道这是否是集合和删除元素的常见问题? 问题答案: 我相信这是Iterator.remove()方法背后的目的,是能够在迭代时从集合中删除一个元素。 例如: