ComputeIfAbsent引发并发ModificationException

时间:2019-06-03 18:54:59

标签: java multithreading

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

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

每当我将刷新时间减少到20秒时,它就会偶尔为某些读者引发ConcurrentModificationException。可以吗?

缩短时间段有什么区别?

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

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

2 个答案:

答案 0 :(得分:3)

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

  

每当我将刷新时间减少到20秒时,它就会偶尔为某些读者引发ConcurrentModificationException。可以吗?

这可能只是巧合。如果减少时间,则只是使线程更有可能尝试访问该映射并将其破坏,因为您没有使用同步集合。如果您的应用程序运行足够的时间,您也有可能在30秒钟的刷新时间内获得它。调试多线程应用程序很困难,因为您可能认为您的应用程序运行正常-但最终结果是,每1000个错误中有1个错误,因为您以错误的方式处理了多线程。

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

答案 1 :(得分:2)

  

是预期的吗?

Javadoc of HashMap中所说(强调他们的意思):

  

请注意,此实现未同步。。如果多个线程同时访问哈希映射,并且至少一个线程在结构上修改了映射,则必须在外部进行同步。 (结构修改是添加或删除一个或多个映射的任何操作;仅更改与实例已经包含的键相关联的值不是结构修改。)

关于是否特别需要ConcurrentModificiationException,尚不清楚。应该期望的是行为未定义

如果幸运的话,会发生异常。例外很好:它们告诉您您做错了什么。如果您不那么幸运,它会自动失败。谁知道在您的特定情况下会发生什么?也许它可以正常工作,也许不能。

如果您希望代码正常运行,请使用已记录的类。