Java 当多个用户在HashMap上操作时,ConcurrentModificationException

Java 当多个用户在HashMap上操作时,ConcurrentModificationException,java,multithreading,jsp,hashmap,Java,Multithreading,Jsp,Hashmap,我有一个HashMap,它存储ID和Name对。对于此映射的每个条目,我将有条件地将其放入另一个HashMap。最后,我将对第二个映射条目执行一些操作。所有这些代码都是用JSP文件编写的 对于单用户请求,这可以正常工作。当一次有多个用户试图访问此文件时,只有一个请求成功,并在其他用户上产生相同的结果 我们可以在日志中看到以下异常: org.apache.jasper.JasperException: java.util.ConcurrentModificationException 地图是这种

我有一个
HashMap
,它存储ID和Name对。对于此映射的每个条目,我将有条件地将其放入另一个
HashMap
。最后,我将对第二个映射条目执行一些操作。所有这些代码都是用JSP文件编写的

对于单用户请求,这可以正常工作。当一次有多个用户试图访问此文件时,只有一个请求成功,并在其他用户上产生相同的结果

我们可以在日志中看到以下异常:

org.apache.jasper.JasperException: java.util.ConcurrentModificationException
地图是这种格式的

Map<String, String> testmap= new HashMap<String, String>();
Map testmap=newhashmap();

不同的请求可能会在不同的线程上运行。您必须在公共数据结构测试图上进行同步


有几种方法可以实现这一点@都铎建议使用锁。这将是一种可能的方式。如果这是一个练习,我建议您阅读一些关于多线程中的同步以及Java中的同步方法的知识。

如果您在对集合进行迭代时修改该集合,无论是从同一个线程还是同时从多个线程执行,都会出现该错误。我怀疑这是第二种情况,因为它发生在多个用户请求中。确保使用锁保护访问(每个映射对象可能有一个锁)。

来自以下java文档:

这个类的所有“集合视图方法”返回的迭代器都是快速失效的:如果在创建迭代器后的任何时候,以任何方式(除了通过迭代器自己的remove方法之外)修改了映射的结构,迭代器将抛出ConcurrentModificationException。因此,在面对并发修改时,迭代器会快速、干净地失败,而不是在将来的不确定时间冒着任意、不确定行为的风险

如前所述,最简单的解决方案是同步对同时迭代/修改的
Map
的访问

Map map = ... //the map object has to be the same for all users calling your jsp

synchronized(map) {
   //do work
}

另请参见

如果您的地图将同时被多个线程访问和修改,请尝试使用更好的地图实现来解决您的问题:地图可以帮您解决问题

final Map<String,String> map = new ConcurrentHashMap<String,String>();

感谢您回复我的帖子“如何使用锁保护访问”,您能给我一些信息吗。@user1659994:基本上,无论您在地图上有一个for循环或一个add/remove,请将其包装到一个
synchronized
块中。确保所有线程都看到相同的锁对象。“concurrenthashmap”是否有助于解决此问题。如果不知道完整的代码,很难说。我认为这是朝着正确方向迈出的一大步。但是,由于您对资源进行了迭代,因此您需要的不仅仅是同步对资源方法的每个调用。您需要同步整个迭代,这意味着某种锁定。通过
synchronize
块或显式锁()@Gray感谢您为我的答案添加了一些风格。我是这里的新手。
final Map map = Collections.synchronizedMap(new HashMap());