hoaz
hoaz

Reputation: 10161

How to clean concurrent map safely

I am trying to solve a problem which seems quite common to me, but I could not find good solution for it.

In a very concurrent environment I need to release resources correctly when client session is destroyed. Here is input:

Here is my current solution:

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

Which exists only because ConcurrentHashMap#values#iterator does not always reflect concurrent puts to resourceMap. I do not like this code and would prefer queue-like code, but unfortunately ConcurrentMap does not provide anything like this:

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

I am looking for solution which is similar to queue-like code above or any alternative approaches to this problem.

Upvotes: 1

Views: 500

Answers (1)

Gray
Gray

Reputation: 116908

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

I would just use an iterator but then again I'm not a Java 8 fan.

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

It's important to note that there are race conditions in this model. Someone could get the resource, go to use it, but at the same time it is being destroyed by this thread.

Upvotes: 1

Related Questions