How to refresh HashMap while clients read from it

匆匆过客 提交于 2021-02-05 09:48:27

问题


I have a static HashMap that is initialized on server startup. Clients initialize their data from this map when they login.
Now I need to refresh this map, but clients can login and get data from this map at the same time.

Can I change reference of map like below while they read? I cant use synchronized because they can read in at the same time and only one thread is writing.

   public void refresh() {
       Map<String, Object> newMap = prepareData();
       map = newMap;
   }

回答1:


Lets assume that "refresh" means that you want to replace all entries in the hashmap with a fresh set loaded from (say) a file.

If the set of keys in the new mapping is a superset of the keys in the original mapping, AND if you application doesn't care if clients can set part of the old mapping and part of the new mapping at the same time, then you could use a ConcurrentHashMap instead of a HashMap, and replace the entries with a sequence of put calls.

However, if keys are (or could be) different, or if the update needs to be atomic from the client's perspective then a ConcurrentHashMap is not going to work. Instead, you need to declare map as a volatile and implement your refresh() method as per your question.

As you point out, using synchronized (or a single-writer-multiple-reader lock) is liable to lead to a concurrency bottleneck.


Note: using a volatile is likely to give better performance than using a ConcurrentHashMap even in the cases where the latter is a viable solution.




回答2:


First of all your map needs to be declared as volatile in order to ensure that each thread has the last version of it, then here is how you could proceed:

public void refresh() {
    synchronized (MyClass.class) {
        Map<String, Object> newMap = prepareData();
        map = Collections.unmodifiableMap(newMap);
    }
}

And your map would be declared as below:

private static volatile Map<String, Object> map = ...



回答3:


If it's ok that clients have stale data, then all you need to do is create a new map and point your static reference at it. If a new client comes along while you're doing this then they get the stale data and no harm is done, if they turn up after the switch (reassignment) to the new values has occurred then they will get the new values. Job done.

If it's not ok then you will also, probably, have to inform other clients that existed before the update about the change. In which case you want to use the observer pattern for the updates. In this pattern it's fine if the client connects during the update, because they will be updated as soon as possible after the update is complete.

BTW: in all cases, you really shouldn't be using 'static' for anything. It'll only lead to problems down the line. Rather, create a non-static singleton that holds the map and inject that into your clients/services/whatever.



来源:https://stackoverflow.com/questions/36621891/how-to-refresh-hashmap-while-clients-read-from-it

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!