2

以下代码,多线程运行:

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 定义,仍然需要同步器?

4

2 回答 2

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!
}

它更快,因为它不涉及再次搜索对象。它更健壮,因为迭代器知道对象已被删除。在许多集合中,您上面显示的代码将由于并发修改而“快速失败”。

于 2013-01-29T15:03:32.337 回答
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);

印刷

{}
于 2013-01-29T15:11:40.790 回答