Suggested Pages

Saturday, May 12, 2012

SoftReference vs WeakReference and Cache Implementation

The main difference between SoftReferences and WeakReferences is that SoftReferences are less aggressive.
A WeakReference tells the Garbage Collector that it can remove an object because there's no need to give it long live, instead a SoftReference tells the Garbage Collector that an object can stay in memory as long as it has no memory needs. A SoftReference, for this reason, is a better candidate than a WeakReference to implement a Cache.
In this post we are going to compare two different caches: the first made with SoftReferences and the second made with WeakReferences. Both the caches work in this manner:
  • Cache hit:vthe system return an entry;
  • Cache missed: the system retrieves the entry out of the cache and then it puts the entry in the cache before it returns.

In the code shown below, there are two classes called ImageLoader. The former makes use of a cache implemented with SoftReference (SoftReferenceCache), the latter makes use of a cache implemented with WeakReference (WeakReferenceCache). As you can see if a cache hit occurs the entry is returned and if a cache missed occurs, a new ValueCache is created and put in the cache. Actually this is an escamotage because ValueCache is usually retrieved in a different manner.

ImageLoader.java (SoftReferenceCache)

package com.simonefolinojavablog.softreferencecache;

import java.util.logging.Level;

public class ImageLoader {

 private static SoftReferenceCache<String, ValueCache> cache = new SoftReferenceCache<String, ValueCache>();

 public static ValueCache getImage(String key) {
  
  ValueCache result = null;

  ValueCache valueCache = (ValueCache) cache.get(key);

  if (valueCache == null) {
   ProjectLogger.PROJECT_LOGGER.getLogger().log(Level.INFO,"entry: " + key + " result: cache miss");
   ValueCache newValue = new ValueCache();
   newValue.setKey(key);
   cache.put(key, newValue);
   result = newValue;
  } else {
   ProjectLogger.PROJECT_LOGGER.getLogger().log(Level.INFO,"entry: " + key + " result: cache hit");
  }
  return result;
 }
}

SoftReferenceCache.java

package com.simonefolinojavablog.softreferencecache;

import java.lang.ref.SoftReference;
import java.util.HashMap;

public class SoftReferenceCache<K extends Comparable<K>, V> {

 private HashMap<K, SoftReference<V>> map = new HashMap<K, SoftReference<V>>();
 
 public V get(K key) {
  SoftReference<V> softReference = map.get(key);

  if (softReference == null) {
   return null;
  } 
  return softReference.get();
 }

 public void put(K key, V value) {
  map.put(key, new SoftReference<V>(value));
 }

}
ImageLoader.java (WeakReferenceCache)

package com.simonefolinojavablog.weakreferencecache;

import java.util.logging.Level;

public class ImageLoader {

 private static WeakReferenceCache<String, ValueCache> cache = new WeakReferenceCache<String, ValueCache>();

 public static ValueCache getImage(String key) {

  ValueCache result = null;

  ValueCache valueCache = (ValueCache) cache.get(key);

  if (valueCache == null) {
   ProjectLogger.PROJECT_LOGGER.getLogger().log(Level.INFO,"entry: " + key + " result: cache miss");
   ValueCache newValue = new ValueCache();
   newValue.setKey(key);
   cache.put(key, newValue);
   result = newValue;
  } else {
   ProjectLogger.PROJECT_LOGGER.getLogger().log(Level.INFO,"entry: " + key + " result: cache hit");

  }
  return result;
 }

}

WeakReferenceCache.java


package com.simonefolinojavablog.weakreferencecache;

import java.lang.ref.WeakReference;
import java.util.HashMap;

public class WeakReferenceCache<K extends Comparable<K>, V> {

 private HashMap<K, WeakReference<V>> map = new HashMap<K, WeakReference<V>>();
 
 public V get(K key) {

  WeakReference<V> WeakReference = map.get(key);

  if (WeakReference == null) {
   return null;
  } 
  return WeakReference.get();
 }

 public void put(K key, V value) {
  map.put(key, new WeakReference<V>(value));
 }

}

These two different caches have different behaviour. Suppose that the Heap increases because of many Strong References, then the cache made with WeakReferences returns many cache miss sooner than the cache made with SoftReferences.

In a future post i'll describe the usage of WeakHashMap

No comments :

Post a Comment

Suggested Pages