Javamex

Java discussion forum to accompany the Javamex web site.

I've read http://www.javamex.com/tutorials/synchronization_concurrency_8_hash...

I'm wondering what the best and most performant option is given that my HashMap will be read intensively by multiple threads whereas it will be only sporadicaly (once every day/week) reloaded by one thread ?

That is, at (web) application startup, I load the Map. After application startup, requests start arriving using that map to check the existence of a particular key, and if so, to fetch the value (object) behind the key and associate it to the object I' m processing.

In the ideal situation I want to block those reading threads until the whole Map is fully-reloaded. How can I accomplish that given that the reloading will only occur by one thread, once in a while ?

If the ideal is not possible would ConcurrentHashMap be an option ?

Thanks,
E

Views: 101

Reply to This

Replies to This Discussion

There are a number of solutions to this depending on a few details of your requirements.

I would probably opt for a plain old (possibly read-only) HashMap to store the data, and concentrate on the problem of how you manage the REFERENCE to this hash map. So you'll have hash map A, and then at some point, a thread is going to construct a brand new hash map B with the updated data, then replace the reference to A with a reference to B.

Now, while the new version of the map is being loaded in, does it matter if threads continue to reference the OLD map UNTIL the new one is actually loaded? If not, then what you essentially have is a boring old volatile reference to a hash map:

private volatile HashMap m;
...
private void loadMapData() {
HashMap newMap = new HashMap();
// load data into newMap
m = newMap;
}

If it DOES matter that accessing threads wait for the new data once loading of the new data has started, then you can use a FutureTask:

private volatile FutureTask
Sorry, some of my answer got chopped. Agh!

So with FutureTask, you have a volatile reference to a FutureTask, whose call() method loads the data:

private volatile FutureTask < Map<String,String>> ft;

Then your loadMapData() actually replaces the ft:

private void loadMapData() {
Callable < Map < String,String>> c = new Callable < Map < String,String>>() {
public Map < String,String> call() {
// load and return map
}
};
ft = new FutureTask(c);
}

private String getData(String key) {
Map < String,String> m = ft.get(); // this will wait for load if necessary
return m.get(key);
}

Then you just have the issue of the VERY FIRST load-- i.e. making sure that the first version of the map has been loaded before the first access. For this you could use a CountDownLatch:

private final CountDownLatch initLatch = new CountDownLatch(1);

then you call await() on the latch at the start of the getData() method and countDown() after setting the map/FutureTask reference.

You could also just use a static initialiser if your situation allowed it. So you do the following in the same class as getData():

static {
loadMapData();
}

This guarantees that the map will be initially loaded before any other call in that class (including any call to getData()).
Thanks for the fast and good advise !

Regarding your question whether it matters if a threads continue to reference the old map while the new one is actually loaded. It could matter.

But in either case I'll investigate a bit more the first (volatile) approach you mentioned.
Does it mean that by using a "volatile" reference to a map it can be replaced while other threads are actually "using" that reference without causing unexpected problems like nullpointexceptions ?

With regards to the FutureTask approach. If I'm understanding things correctly then the "reader" threads use the getData method to retrieve data from the map and this getData method will wait if a load (called in another thread) is in progress ? Is that right ?

Is using a ConcurrentHashmap still another alternative (assuming that the reader threads can continu accessing the map while it's being reloaded) ? And if so is a ConcurrentHashMap faster than using a "normal" HashMap ?

Reply to Discussion

RSS

© 2024   Created by Neil Coffey.   Powered by

Badges  |  Report an Issue  |  Terms of Service