So, currently the solution that I am thinking is to have a hashmap with multiple readers and once it expires, a daemon thread will fetch the data from the datasource and create a new map and once its done will take the lock on the old HashMap and then copy the newly created map to the old one.
That sounds right. If, as you imply in your message, no one is modifying the HashMap after it has been created, you can safely use it with multiple threads as long as you share it correctly. To ensure immutability, you should wrap the map using Collection.unmodifiableMap(map)
.
To share the map with the threads, you will need to make it a volatile field that all of the threads access. Something like:
protected volatile HashMap map = null;
With it being volatile
then you don't need to do any locking. You update method then looks like:
// no need to have synchronized here
HashMap updateMap( HashMap newMap ) {
HashMap oldMap = this.map;
this.map = Collection.unmodifiableMap(newMap);
return oldMap;
}
None of your other methods need to be synchronized
as well. volatile
fields will perform a lot better because the threads will only cross a read memory barrier when they access the shared map and only a write memory barrier when it is updated. With a synchronized
keyword, the threads cross a read and write barrier every time. Even worse, the synchronized
keyword has lock overhead that insures mutex which you don't need.
Will copying the data to new map take more time?
Copying the data to the new map will take time but no more than a typical copying of data between HashMaps. What is different is that the volatile
field access can be much slower than direct field access because of the memory barriers that are crossed.