简体   繁体   English

遍历ConcurrentHashMap后使用get()

[英]Using get() after iterating over ConcurrentHashMap

I have a code snippet like this: 我有一个这样的代码片段:

    private final Map<String, Information> infoMap = new ConcurrentHashMap<String, Information>();

    synchronized (infoMap) {
        for (final String nameAndVersion : infoMap.keySet()) {
            final Information info = infoMap.get(nameAndVersion);
            final String name = info.getName();
            names.add(name);
        }
    }

The question I have is: is it necessary to use the synchronized block as shown, as the operation from keySet() to get() is not atomic (and therefore the map could be updated between one call and the next, as a ConcurrentHashMap is only thread-safe for each individual call)? 我的问题是:是否需要使用如图所示的同步块,因为从keySet()到get()的操作不是原子的(因此,可以在一个调用与下一个调用之间更新映射,因为ConcurrentHashMap是每个调用仅具有线程安全性)?

Should I iterate over the EntrySet instead, to ensure the complete iterator is constructed? 我是否应该遍历EntrySet以确保构造完整的迭代器?

I believe the synchonized block is needed if keySet() and get() is called, but I am not sure on this. 我相信如果调用keySet()和get(),则需要同步块,但是对此我不确定。

Thanks in advance for responses. 预先感谢您的回复。

It depends on the outcome you require. 这取决于您需要的结果。

Currently, if the infoMap is modified in another thread it is quite possible for info to be null when the get is called - which would cause an NPE on the call to getName . 当前,如果在另一个线程中修改了infoMap ,则在infoMap getinfo很可能为null ,这将导致对getName的调用中出现NPE If that is the required behaviour or you are confident that this method is the only place the Map will be modified then just synchronized is sufficient. 如果这是必需的行为,或者您确信此方法是将要修改Map的唯一位置,那么仅synchronized就足够了。

Using EntrySet will not side-step the issue - it will only postpone it. 使用EntrySet不会EntrySet问题-只会推迟它。 All that will achieve will be to ensure that if an entry is removed during iteration you will not be presented with an immediate issue - but obviously you may return data that is no longer in the map. 所有要做的就是确保,如果在迭代过程中删除某个条目,则不会立即出现问题-但是显然,您可能返回的映射图中不再存在的数据。

You should always use entrySet() method when iterating over keys and values of an HashMap. 遍历HashMap的键和值时,应始终使用entrySet()方法。 Moreover in ConcurrentHashMap, entrySet() will never throw "ConcurrentModificationException" (see Javadoc) 此外,在ConcurrentHashMap中,entrySet()将永远不会抛出“ ConcurrentModificationException” (请参阅Javadoc)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM