Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HashMap with weak values

Tags:

I'm implementing a cache for Objects stored persistently. The idea is:

  • Method getObjectFromPersistence(long id); ///Takes about 3 seconds
  • Method getObjectFromCache(long id) //Instantly

And have a method: getObject(long id) with the following pseudocode:

synchronized(this){     CustomObject result= getObjectFromCache(id)     if (result==null){        result=getObjectFromPersistence(id);        addToCache(result);     }     return result; } 

But I need to allow the CustomObject to be collected by the garbage collector. Until now I was using an HashMap<Long,WeakReference<CustomObject> for the implementation. The problem is that over the time the HashMap becomes filled of empty WeakReferences.

I've checked WeakHashMap but there the keys are weak (and the values are still strong references) so having the longs with WeakReferences have no sense.

Whats the best solution for solving this problem? Is there some "inverse WeakHashMap" or something similar?

Thanks

like image 824
Addev Avatar asked Nov 16 '12 08:11

Addev


People also ask

What is weak hash map?

WeakHashMap is an implementation of the Map interface that stores only weak references to its keys. Storing only weak references allows a key-value pair to be garbage-collected when its key is no longer referenced outside of the WeakHashMap. This class provides the easiest way to harness the power of weak references.

Where do I use WeakHashMap?

You can use a WeakHashmap to reduce the chance of a memory leak as a result of caching some object. The WeakHashMap will automatically remove entries whenever all references to the key are removed.

Is WeakHashMap synchronized?

WeakHashMap can be used as in-memory cache, allowing keys to expire when they are weakly reachable. Unfortunately this class is not thread-safe. It's entirely possible that un-synchronized invocation of the WeakHashMap. get(Object) method will result in infinite busy waiting loop starving all other threads.

Is WeakHashMap thread safe?

The purpose of the map is to translate exceptions and other tasks from one version to another. This map can get corrupted, which can cause threads to get stuck when executing the WeakHashMap method, which is not thread safe and can lock the entire application.


1 Answers

You can use the Guava MapMaker for this:

ConcurrentMap<Long, CustomObject> graphs = new MapMaker()    .weakValues()    .makeMap(); 

You can even include the computation part by replacing makeMap() with this:

   .makeComputingMap(        new Function<Long, CustomObject>() {          public CustomObject apply(Long id) {            return getObjectFromPersistence(id);          }        }); 

Since what you are writing looks a lot like a cache, the newer, more specialized Cache (built via a CacheBuilder) might be even more relevant to you. It doesn't implement the Map interface directly, but provides even more controls that you might want for a cache.

You can refer to this for a detailed how to work for CacheBuilder and here is an example for fast access:

LoadingCache<Integer, String> cache = CacheBuilder.newBuilder()    .maximumSize(100)    .expireAfterWrite(10, TimeUnit.MINUTES)    .build(        new CacheLoader<Integer, String>() {            @Override            public String load(Integer id) throws Exception {                return "value";            }        }    );  
like image 92
Joachim Sauer Avatar answered Oct 23 '22 17:10

Joachim Sauer