我正在努力解决一个对我来说很常见的问题,但我找不到合适的解决方案。
在非常并发的环境中,我需要在销毁客户端会话时正确释放资源。这是输入:
ConcurrentHashMap
存储所有已分配的资源,此处需要map来索引资源这是我目前的解决方案:
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();
}
我正在寻找类似于上面类似队列的代码的解决方案或任何替代解决此问题的方法。
答案 0 :(得分:1)
我不喜欢这段代码并且更喜欢类似队列的代码,但遗憾的是ConcurrentMap不提供类似这样的代码......
我只是使用迭代器,但我又不是Java 8粉丝。
while (!resourceMap.isEmpty()) {
Iterator<Resource> iterator = resourceMap.values().iterator();
while (iterator.hasNext()) {
Resource resource = iterator.next();
iterator.remove();
resource.destroy();
}
}
重要的是要注意此模型中存在竞争条件。有人可以获得资源,去使用它,但同时它被这个线程摧毁。
答案 1 :(得分:0)
我知道您有许多资源需要销毁,并且将资源放入此映射是一种请求异步销毁资源的方法。
并且,您有一个工作线程来轮询此地图并销毁它在其中找到的所有内容。
由于您要“排队”项目以便对它们请求操作,因此您可以使用ExecutorService。 (或者根据队列和工作线程写一些东西,它总结了执行者服务)。
使用执行器,一个例子是
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ResourceDestroyer {
ExecutorService es = Executors.newSingleThreadExecutor();
//"destroy" will be executed by the worker thread
public void destroyResource(Resource r) {
es.submit(r::destroy);
}
}