首页 > 解决方案 > ComputeIfAbsent 抛出 concurrentModificationException

问题描述

我有一个 Hashmap,我在其中维护不同类型的阅读器到它们各自的 java 类实现的映射。我有一个支持 32 种阅读器的多线程 Java 服务器。

您可以假设每 30 秒,getReader() 会被每种类型的阅读器的 1000 个对象在内部调用一次。

每当我将刷新时间减少到 20 秒时,它就会开始偶尔为一些读者抛出 ConcurrentModificationException。是预期的吗?

缩短时间段有什么不同?

class Mapper {
    Map<String, Reader> READER = new HashMap<>();

    public static Reader getReader(type) {
        Reader reader = READER.computeIfAbsent(type, k -> new ReaderImpl());
    }
}

标签: javamultithreading

解决方案


如果您的地图可以被多个线程访问,您应该使用ConcurrentHashMap 。

每当我将刷新时间减少到 20 秒时,它就会开始偶尔为一些读者抛出 ConcurrentModificationException。是预期的吗?

这可能只是巧合。如果您减少时间,您只会使线程更有可能尝试访问映射并破坏它,因为您没有使用同步集合。还有一种可能是,如果您运行应用程序的次数足够多,那么您也可以在 30 秒的刷新时间内获得它。调试多线程应用程序很困难,因为您可能认为您的应用程序运行良好 - 但最终结果表明,有 1000 个应用程序会出现错误,因为您以错误的方式处理多线程。

正如安迪·特纳(Andy Turner)正确指出的那样-您很幸运ConcurrentModificationException出现了。如果您没有收到异常,并不意味着问题不存在。如果您在生产中运行时在应用程序中收到此类错误,情况会更糟。


推荐阅读