我有ConcurrentHashMap
订阅,其中包含另一个对象( sessionCollection ),我需要执行以下迭代操作:
subscriptions.values().forEach(sessionCollection ->
sessionCollection.removeAllSubscriptionsOfSession(sessionId));
其中sessionCollection.removeAllSubscriptionsOfSession
对 sessionCollection 内的集合(也是ConcurrentHashMap
)执行另一次迭代操作:
// inside SessionCollection:
private final ConcurrentHashMap<String, CopyOnWriteArrayList<String>> topicsToSessions =
new ConcurrentHashMap<>();
public void removeAllSubscriptionsOfSession(String sessionId) {
// Remove sessions from all topics on record
topicsToSessions.keySet().forEach(topicSessionKey ->
removeTopicFromSession(sessionId, topicSessionKey));
}
进行这种整体原子操作的步骤是什么?
答案 0 :(得分:1)
ConcurrentHashMap
具有批处理操作(forEach*()
),但它们与整个地图不是原子的。在地图上进行原子批量更改的唯一方法是自己实现所有必要的同步。例如,通过显式使用synchronized
块或通过为地图创建包装器(或扩展)来处理需要的同步。在这种情况下,简单的HashMap
就足够了,因为你必须进行同步:
public class SubscriptionsRegistry {
private final Map<Integer, SessionCollection> map = new HashMap<>();
public synchronized void removeSubscriptions(Integer sessionId) {
map.values().forEach(...);
}
public synchronized void addSubscription(...) {
...
}
...
}
您还希望保护主题到会话的地图(至少是其可修改的版本)不会泄漏到SubscriptionsRegistry
之外,因此没有人能够在没有正确同步的情况下修改它们。