ConcurrentHashMap vs ReentrantReadWriteLock based Custom Map for Reloading

后端 未结 3 572
无人及你
无人及你 2021-02-04 12:24

Java Gurus,

Currently we have a HashMap which is being read frequently and modified occasionally and w

相关标签:
3条回答
  • 2021-02-04 13:01

    It seems you are not sure as to how what Peter Lawrey suggests can be implemented. It could look like this:

    class YourClass {
        private volatile Map<String, SomeApplicationObject> map;
    
        //constructors etc.
    
        public void reload() {
            Map<String,SomeApplicationObject> newMap = getNewValues();
            map = Collections.unmodifiableMap(newMap);
        }
    }
    

    There are no concurrency issues because:

    • The new map is created via a local variable, which by definition is not shared - getNewValues does not need to be synchronized or atomic
    • The assignement to map is atomic
    • map is volatile, which guarantees that other threads will see the change
    0 讨论(0)
  • 2021-02-04 13:07

    This sounds a lot like Guava's Cache, though it really depends how you're populating the map, and how you compute the values. (Disclosure: I contribute to Guava.)

    The real question is whether or not you can specify how to compute your SomeApplicationObject given the input String. Just based on what you've told us so far, it might look something like this...

    LoadingCache<String, SomeApplicationObject> cache = CacheBuilder.newBuilder()
       .build(
           new CacheLoader<String, SomeApplicationObject>() {
             public SomeApplicationObject load(String key) throws AnyException {
               return computeSomeApplicationObject(key);
             }
           });
    

    Then, whenever you wanted to rebuild the cache, you just call cache.invalidateAll(). With a LoadingCache, you can then call cache.get(key) and if it hasn't computed the value already, it'll get recomputed. Or maybe after calling cache.invalidateAll(), you can call cache.loadAll(allKeys), though you'd still need to be able to load single elements at a time in case any queries come in between the invalidateAll and loadAll.

    If this isn't acceptable -- if you can't load one value individually, you have to load them all at once -- then I'd go ahead with Peter Lawrey's approach -- keep a volatile reference to a map (ideally an ImmutableMap), recompute the whole map and assign the new map to the reference when you're done.

    0 讨论(0)
  • 2021-02-04 13:12

    Since you are reloading the map, I would replace it on a reload.

    You can do this by using a volatile Map, which you replace in full when it is updated.

    0 讨论(0)
提交回复
热议问题