Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 删除已删除的ConcurrentHashMap元素有多安全?_Java_Multithreading_Synchronization_Concurrenthashmap - Fatal编程技术网

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);
{}