java.util.concurrent.ExecutionException:java.util.ConcurrentModificationException

java.util.concurrent.ExecutionException:java.util.ConcurrentModificationException,java,executorservice,java.util.concurrent,callable,Java,Executorservice,Java.util.concurrent,Callable,在执行以下代码时,我收到一个并发修改异常: mymap是一个全局变量,是一个HashMap Callable<String> task = new Callable<String>() { @Override public String call() { mymap.put("myid", "id2"); mymap.put("myname", "joe"); String id = mymap.ge

在执行以下代码时,我收到一个并发修改异常:

mymap是一个全局变量,是一个HashMap

 Callable<String> task = new Callable<String>() {
   @Override
   public String call() {           
      mymap.put("myid", "id2");
      mymap.put("myname", "joe");
      String id = mymap.get("myid");
      System.out.println("id is: "+ id+ ", mymap BEFORE: "+mymap.toString());
      mymap.remove("myid");
      System.out.println("id is: "+ id+ ", mymap AFTER: "+mymap.toString());
      return id;
   }
 };

 List<Callable<String>> tasks = Collections.nCopies(7, task);
 ExecutorService executorService = Executors.newFixedThreadPool(7);
 List<Future<String>> futures = executorService.invokeAll(tasks);
 List<String> resultList = new ArrayList<String>(futures.size());

 for (Future<String> future: futures){
    resultList.add(future.get());
 }

但是如果我尝试

System.out.println("srcNode AFTER: "+srcNode.toString()+ ", id: "+id);
相反,错误似乎消失了。有什么线索吗?

HashMap不是线程安全的

如果要同步(即线程安全映射),请使用Collections.synchronizedMap包装HashMap:

或者使用ConcurrentHashMap:


由于有多个线程修改同一实例,因此会出现此错误。关于,

为什么一种观点有效而另一种观点无效

线程不能保证每次都提供相同的结果。如果你多次执行这个程序,你可能会得到不同的输出,没有异常,不同行的异常等等

示例-我只执行了这个程序3次,执行成功2次,第三次出现并发异常


总之,不能保证线程的执行顺序或时间。为了避免这些错误,请使用线程安全的同步或哈希表,但这是以性能为代价的。另外,将mymap声明为方法的局部变量也会起作用——因为每个线程都有自己的局部变量副本——但我假设它是一个实例变量是有原因的。

它是一个HasHMap。。。谢谢你指出这一点。@chapstick u r using multi-threading??我没有使用multi-threading,但我试图模拟一种情况,如果我在一个多用户环境中,可能会发生并发执行。但我认为问题是我的所有线程实际上都共享同一个mymap实例。尽管如此,它并没有解释为什么一个print语句工作而另一个不工作。更改调试消息时出现的错误消失表明存在竞争条件。集合不是集合框架的一部分吗?它们是线程安全的吗?顺便说一句,当您坐下来思考ConcurrentSkipListMap的工作原理和含义时,ConcurrentSkipListMap的后台数据结构是我最喜欢的数据结构。
System.out.println("id is: "+ id+ ", mymap AFTER: "+mymap.toString()); 
System.out.println("srcNode AFTER: "+srcNode.toString()+ ", id: "+id);