如何安全地清理并发映射

How to clean concurrent map safely

我正在尝试解决一个对我来说很常见的问题,但我找不到好的解决方案。

在高度并发的环境中,我需要在客户端会话被销毁时正确释放资源。这里是输入:

这是我目前的解决方案:

while (!resourceMap.isEmpty()) {
    Map<Integer, Resource> toDestroy = new HashMap<>(resourceMap);
    for (Resource resource : toDestroy.values()) {
        resource.destroy();
    }
    resourceMap.keySet().removeAll(toDestroy.keySet());
}

之所以存在,是因为 ConcurrentHashMap#values#iterator 并不总是反映对 resourceMap 的并发放置。我不喜欢这段代码,更喜欢类似队列的代码,但不幸的是 ConcurrentMap 不提供这样的代码:

while ((Map.Entry<String, Resource> entry = resourceMap.removeAny()) != null) {
    entry.value().destroy();
}

我正在寻找类似于上述队列代码的解决方案或解决此问题的任何替代方法。

I do not like this code and would prefer queue-like code, but unfortunately ConcurrentMap does not provide anything like this ...

我只会使用迭代器,但我又不是 Java 8 的粉丝。

while (!resourceMap.isEmpty()) {
    Iterator<Resource> iterator = resourceMap.values().iterator();
    while (iterator.hasNext()) {
       Resource resource = iterator.next();
       iterator.remove();
       resource.destroy();
    }
}

请务必注意此模型中存在竞争条件。有人可以拿到资源,去使用它,但同时它正在被这个线程销毁。