3

I have a console Java application that needs some data from the database. As the application is running constantly, every 30 seconds, in order to lower the strain on the DB i'm using some sort of cache for the data.

Because there isn't a large amount of the needed data in the database, i'm using singleton Hashmap as my cache. My cache class looks like this:

public class Cache extends Hashmap<Integer, Hashmap<Integer, ArrayList<String>> {
//some code
}

Every 5 minutes system will refresh the cache by:

1) calling "clear()" for the existing data 2) filling the cache with new data from the db.

Tell me, if i call the "clear()" for the structure i have ("nested" hashmaps) will Java clear all the data containd under my cache keys, or i'll end up with memory leaks?

guest86
  • 2,894
  • 8
  • 49
  • 72
  • Short answer: Yes clear() works perfectly. Long answer (and it seems as an duplicate): http://stackoverflow.com/questions/16231387/good-way-to-clear-nested-maps-in-java – tea2code Sep 04 '13 at 08:44
  • It releases the key/value objects in the map, but keeps the backing array/table. – Thomas Jungblut Sep 04 '13 at 08:48
  • Sounds like a memory leak. Have you ensured all relevant db-related objects dont refer to items in your hashmaps? ...e.g. `ResultSet`, etc – vikingsteve Sep 04 '13 at 08:53

2 Answers2

2

You can do this, but I suggest a better alternative is to replace it. This will be more efficient if you have multiple threads.

public class Cache {
     private Map<Integer, Map<Integer, List<String>>> map;

     public Cache(args) {
     }

     public synchronized Map<Integer, Map<Integer, List<String>>> getMap() {
          return map;
     }

     // called by a thread every 30 seconds.
     public void updateCache() {
          Map<Integer, Map<Integer, List<String>>> newMap = ...
          // build new map, can take seconds.

          // quickly swap in the new map.
          synchronzied(this) {
              map = newMap;
          }
     }
}

This is both thread safe and has a minimum of impact.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • Is the map you create when building a new map a `ConcurrentHashMap`? Seems like it would need to be to keep this thread safe. – cyon Sep 04 '13 at 09:07
  • You only need a ConcurrentMap if you are both reading and writing. In this case, it is only writing and after a synchronized block, only reading. No more lock/thread safety is required. – Peter Lawrey Sep 04 '13 at 09:41
  • Ah I see you only write to the map as you build it from the database and then wrap it perhaps in an `unmodifiableMap`. However, do you not expose yourself to a memory leak problem? If users assign the reference returned by `getMap()` to some variable then it will not get GCed after `updateCache`. – cyon Sep 04 '13 at 10:00
  • 1
    You shouldn't have any `getMap()` method. With the principle of encapsulation you want to hide the exact implementation with a map. The cache class should rather have some `get(Integer key)` methods to access the data. – Obenland Sep 04 '13 at 17:29
  • @Xean +1, though it might be `getList(int key1, int key2)` or even a visitor for the elements of the list. – Peter Lawrey Sep 04 '13 at 17:31
0

This article is helpful for you.

Is Java HashMap.clear() and remove() memory effective?

And, HassMap is not thread safe. If you want using singleton HashMap, You had better use ConcurrentHashMap.

Community
  • 1
  • 1