【发布时间】:2012-03-12 10:16:39
【问题描述】:
我有一个 HashMap,它的类型为 HashMap<String,HashMap<String,int>> 现在我需要遍历这个 HashMap 并删除任何键值为 0 的内部 HashMap。
如果这样的删除使内部 HashMap 为空,则内部 HashMap 的对应键将从外部 HashMap 中删除。我尝试对其进行迭代,然后删除符合要求的元素,但这会给我带来ConcurrentModificationException。
我尝试了以下代码:
synchronized(MyConstants.cliListUpdateList)
{
synchronized(MyConstants.cliList)
{
outerEntries = MyConstants.cliListUpdateList.entrySet();
outerIterator = outerEntries.iterator();
while(outerIterator.hasNext())
{
outerEnt = (Entry) outerIterator.next();
innerHashMap = (HashMap) outerEnt.getValue();
synchronized(innerHashMap)
{//synchronize innerhashmap
innerEntries = innerHashMap.entrySet();
innerIterator = innerEntries.iterator();
synchronized(innerIterator)
{
while(innerIterator.hasNext())
{
innerEnt = (Entry) innerIterator.next();
int k = Integer.parseInt((String)innerEnt.getValue());
if(k==0)
{
innerHashMap.remove(innerEnt.getKey());
if(innerHashMap.isEmpty())
{
MyConstants.cliListUpdateList.remove(outerEnt.getKey());
}
ArrayList ports = (ArrayList) MyConstants.cliList.get(outerEnt.getKey());
ports.remove((String)innerEnt.getKey());
if(ports.isEmpty())
{
MyConstants.cliList.remove(outerEnt.getKey());
}
}
else
{
k--;
innerHashMap.put(innerEnt.getKey(), k+"");
MyConstants.cliListUpdateList.put(outerEnt.getKey(), innerHashMap);
}
}
}
}//synchronize innerhashmap
}
System.out.println(MyConstants.cliListUpdateList + " <---> "+ MyConstants.cliList);
}
}
我在这一行遇到了异常:innerEnt = (Entry) innerIterator.next();。我尝试了 Iterator 类提供的 remove 方法。但这也不好。
编辑
从 Java 文档中我知道很多 if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this(ConcurrentModificationException) exception 但我需要完全相同的功能。
【问题讨论】:
-
我尝试了尽可能多的同步块,但效果不佳:(
-
同步不会拯救你,因为这都是由单个线程引起的。同步用于序列化多个线程对单个非线程安全容器(例如
HashMap)执行的操作。
标签: java multithreading exception collections concurrentmodification