执行以下代码时,我收到并发修改异常:
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());
}
行引发异常:
resultList.add(future.get());
和
System.out.println("id is: "+ id+ ", mymap AFTER: "+mymap.toString());
但是,如果我尝试
System.out.println("srcNode AFTER: "+srcNode.toString()+ ", id: "+id);
相反,错误似乎消失了。关于最新情况的任何线索?
答案 0 :(得分:0)
HashMap
不是线程安全的。
如果您想要同步(即线程安全)地图,请使用Collections.synchronizedMap()
来包装您的HashMap:
或使用ConcurrentHashMap
:
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentHashMap.html
答案 1 :(得分:0)
由于有多个线程修改同一个实例 - 您会收到此错误。关于,
为什么一个点语句有效而另一个
不保证线程每次都提供相同的结果。如果你多次执行这个程序,你可能得到不同的输出(没有异常,不同行的异常等)。
示例 - 我刚刚执行了3次这个程序,执行成功了2次,并且第三次得到并发异常。
总而言之,我们无法保证线程执行的顺序或时间。为了避免这些错误,使用同步或HashTable是线程安全的 - 但是它会以性能为代价。此外,将mymap声明为方法的局部变量也可以 - 因为每个线程都有自己的局部变量副本 - 但我假设它是一个实例变量,原因就在这里。