ConcurrentHashMap vs ReentrantReadWriteLock custom map to reload

Java gurus

Currently we have a HashMap<String,SomeApplicationObject> , which is often read and changed from time to time , and we have problems that occur during modification / reload, the Read operation returns null which is unacceptable.

To fix this, I have the following options:

but. Use ConcurrentHashMap

What the first choice looks like, but the operation we're talking about is reload() means clear() , followed by replaceAll() . Therefore, if Map replaceAll() clear() and pre replaceAll() , it returns null, which is undesirable. Even if I synchronize , this does not solve the problem.

C. Create another implementation based on ReentrantReadWriteLock

Where would I create the Write Lock function before reload() . It seems more appropriate, but I feel that there is something already available for this, and I do not need to reinvent the wheel.

What is the best way out?

EDIT Is any collection available with this feature?

+8
java design locking concurrenthashmap reentrantreadwritelelock
source share
3 answers

It seems you are not sure how what Peter Laurie offers can be realized. It might 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 is no concurrency problem because:

  • A new map is created through a local variable, which by definition is not shared - getNewValues does not need to be synchronized or atomically
  • The purpose of map is atomic
  • map is volatile, which ensures that other threads will see the change
+4
source share

Since you are reloading the card, I would replace it with a reboot.

You can do this using a mutable map, which you fully update when you update it.

+8
source share

This is very similar to Guava Cache , although it really depends on how you fill the map and how you calculate the values. (Disclosure: I contribute to Guava.)

The real question is: can you specify how to calculate your SomeApplicationObject based on String input. Based on what you have 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, when you want to restore the cache, you simply call cache.invalidateAll() . Using LoadingCache you can call cache.get(key) , and if it has not yet calculated the value, it will be recalculated. Or maybe after calling cache.invalidateAll() you can call cache.loadAll(allKeys) , although you still need to load individual items at a time if any requests come in between invalidateAll and loadAll .

If this is unacceptable - if you cannot load one value separately, you must download them all at once - then I would continue the approach of Peter Lowry - save the volatile map link (ideally a ImmutableMap ), recompose the entire map and assign a new map to the link when you are done.

+5
source share

All Articles