如果是以下代码,请由多个线程运行:
private static final Map<String, keyinfo> mapKeys = new ConcurrentHashMap<String, keyinfo>();
private static void purgeOldKeys() {
for (Map.Entry<String, keyinfo> key : mapKeys.entrySet()) {
if(key.getValue().createTime + keyCacheTime < getCurrentDBTime())
mapKeys.remove(key);
}
}
我可以避开同步器吗?
或者因为删除已经删除的元素,没有根据JavaDoc定义,仍然需要同步器?
答案 0 :(得分:5)
通常,当从集合中删除时,使用完整的Iterator
API而不是懒惰的“foreach”概念会更清晰(也更快!)。
iterator.remove();
不会使迭代器失效;它知道它的位置。使用这种模式:
for (Iterator<> iter = map.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry<> entry = iter.next();
if (testRemoval(entry))
iter.remove(); // <----- remove using the iterator position!
}
它更快,因为它不再涉及搜索对象。它更健壮,因为迭代器知道对象已被删除。在许多集合中,由于并发修改,上面显示的代码将“快速失败”。
答案 1 :(得分:4)
1)此代码无法删除任何内容,因为其中存在错误 - mapKeys.remove(key);
- 代码中的键实际上是Map.Entry。它应该是
for (Map.Entry<String, keyinfo> e : map.entrySet()) {
if (e.getValue().createTime + keyCacheTime < getCurrentDBTime())
map.remove(e.getKey());
}
}
2)至于在ConcurrentHashMap上迭代时删除条目是安全的,ConcurrentHashMap.entrySet API
The view's iterator is a "weakly consistent" iterator that will never throw ConcurrentModificationException
并且此测试证实了它
Map<String, String> map = new ConcurrentHashMap<String, String>();
map.put("1", "2");
map.put("2", "2");
map.put("3", "3");
for (String k : map.keySet()) {
map.remove(k);
}
System.out.println(map);
打印
{}