4

The first thread is of JMS subscriber that listens to a topic. As soon as it gets a message it adds/updates/deletes entries in a hashmap. Another thread runs after every 2 mins using TimerClass and reads the contents of the same hashmap and stores it in a file and clears the hashmap. Please suggest what kind of hashmap- concurrent or synchronized should be used? is there any other way to achieve this ?

Yamini
  • 73
  • 7
  • Without a purpose it is hard to suggest a solution. The synchronization level strongly depends on other demands. – Jan Dec 13 '13 at 12:09
  • I would suggest go for synchronizing the HashMap – Sachin Dec 13 '13 at 12:12
  • My code basically has one hashmap whose contents will be added/updated by first thead. What i want to ask is if the second thread that runs after 2 mins to read same hashmap and clear it will be affected by first thread that is continuously running ? is there a possiblity of losing some contents of hashmap that might have been wriiten while i am trying to clear it ? – Yamini Dec 13 '13 at 12:15
  • Hi sachin, by synchronizing hashmap you mean every call to get, put ,clear should be put in synchronized block ? – Yamini Dec 13 '13 at 12:17

4 Answers4

2

Synchronization will be necessary. Since HashMap is not synchronized.

Use Collections.SynchronizedMap or move to Hashtable

Amit G
  • 2,293
  • 3
  • 24
  • 44
  • Just to clear my doubt, If I use collections.SynchornizedMap then i need to put all calls to get,put,clear method in synchronized block ? Synchronized(map){} . Also if i use Hashtable then i don't need to take of synchronization ? – Yamini Dec 13 '13 at 12:23
  • (BTW Hashtable is synchronized) if you are not invoking HashMap operation more 10k/sec, I will recommend you to use Hashtable. No code changes will be required. Quick n easy. – Amit G Dec 13 '13 at 12:25
2

You can have the second thread atomically replace the hashmap with an empty new one, wait for a bit and store the data from the old one.

To make the "wait a bit" more precise, you can, if there's no clear upper limit to the processing time of one message, have the first thread lock the map for as long as it's using it. Then the second thread can acquire the lock before writing the contents, so that it's sure the first thread is done writing the last message's changes to the map.

flup
  • 26,937
  • 7
  • 52
  • 74
1

The simplest and probably the most efficient solution would be to use a regular HashMap within a synchronized block. The writer would be as follows:

synchronized(mapLock)
{
  map.put(...)
}

The purging thread would then be able to simply replace the map with a new empty one:

Map oldMap; 
synchronized(mapLock)
{
  oldMap = map;
  map = new HashMap<...>();
}
store(oldMap);

This would ensure that the purging thread remains in the critical section for as short as possible.

Currently I can't see any advantage of using ConcurrentHashMap in this scenario. That could be different if multiple JMS threads would be running.

Bartosz Klimek
  • 555
  • 2
  • 5
0

How about simply swapping out the hash map? So thread 2 begins by setting the hashmap used by thread 1 to another and then does whatever it needs to do with thread 2. That way you won't have to deal with serialisation. so

storemap(){
 mapcopy=thread1.map;
 thread1.map=new Hashmap<Object>();
 store(mapcopy);
}
Thijser
  • 2,625
  • 1
  • 36
  • 71