Java 删除已删除的ConcurrentHashMap元素有多安全?
在以下代码的情况下,由多个线程运行:Java 删除已删除的ConcurrentHashMap元素有多安全?,java,multithreading,synchronization,concurrenthashmap,Java,Multithreading,Synchronization,Concurrenthashmap,在以下代码的情况下,由多个线程运行: 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.ge
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);
}
}
private static final Map mapKeys=new ConcurrentHashMap();
私有静态void purgeOldKeys(){
对于(Map.Entry键:mapKeys.entrySet()){
if(key.getValue().createTime+keyCacheTime
我可以避开同步器吗
或者因为删除已经删除的元素不是根据JavaDoc定义的,所以仍然需要同步器?一般来说,从集合中删除时,使用完整的迭代器
API而不是懒惰的“foreach”概念会更干净(更快!)
迭代器.remove()代码>不会使迭代器无效;它知道它当时的位置。使用此模式:
for (Iterator<> iter = map.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry<> entry = iter.next();
if (testRemoval(entry))
iter.remove(); // <----- remove using the iterator position!
}
for(迭代器iter=map.entrySet().Iterator();iter.hasNext();){
Map.Entry=iter.next();
if(测试移除(输入))
iter.remove();//1)此代码无法删除任何内容,因为其中存在错误-mapKeys.remove(key);
-代码中的key实际上是一个Map.Entry。它应该是
for (Map.Entry<String, keyinfo> e : map.entrySet()) {
if (e.getValue().createTime + keyCacheTime < getCurrentDBTime())
map.remove(e.getKey());
}
}
这个测试证实了这一点
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);
我不认为你能做到这一点,因为for循环使用的是fail-fast迭代器。是的,这段代码连一个线程都不能工作!我在回答之前进行了测试:)+1点。是的,OP选择的字段键
是一个映射。条目
非常不幸。谢谢,我猜我已经习惯了想法错误或者checker:)。但是,问题仍然存在-如果多个线程调用了此函数,我是否需要同步整个块,或者remove将在没有引起任何问题的情况下以静默方式失败(同样,文档说没有指定行为)。文档说,对于remove(key)
“如果表中没有键,此方法将不起任何作用。”-我希望iterator.remove的行为也一样。那么为什么不给它一次测试运行呢?如果失败,上面的代码看起来不会造成损害。Java文档中:如果在迭代过程中以任何方式修改基础集合而不是调用此方法,则迭代器的行为是未指定的。因此如果ther thread对此进行了修改,会发生什么情况?代码是更广泛线程的一部分,并且可能会影响某些操作如果它失败,那么上述示例是否有可能总是错过第一个元素?即,在检查之前总是跳转到next()元素。next()
call是获取第一个元素的正确方法。和iterator.remove()
是您可以删除的最好方法。至少对于非并发哈希映射:是的,另一个线程可能会触发ConcurrentModificationException
,是的,然后您应该对此做好准备。ConcurrentHashMap版本似乎具有快照语义-可能是next()返回的元素
可能已被删除,您可能会错过同时添加的元素。
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);
{}