SoftReference vs WeakReference and Cache Implement

SoftReference vs WeakReference and Cache Implementation

The main difference between  SoftReferences and  WeakReferences is that  SoftReferences are less aggressive. 
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) 
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
packagecom.simonefolinojavablog.softreferencecache;
 
importjava.util.logging.Level;
 
publicclassImageLoader {
 
 privatestaticSoftReferenceCache<String, ValueCache> cache =newSoftReferenceCache<String, ValueCache>();
 
 publicstaticValueCache 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 =newValueCache();
   newValue.setKey(key);
   cache.put(key, newValue);
   result = newValue;
  }else{
   ProjectLogger.PROJECT_LOGGER.getLogger().log(Level.INFO,"entry: "+ key +" result: cache hit");
  }
  returnresult;
 }
}

SoftReferenceCache.java 
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
packagecom.simonefolinojavablog.softreferencecache;
 
importjava.lang.ref.SoftReference;
importjava.util.HashMap;
 
publicclassSoftReferenceCache<KextendsComparable<K>, V> {
 
 privateHashMap<K, SoftReference<V>> map =newHashMap<K, SoftReference<V>>();
  
 publicV get(K key) {
  SoftReference<V> softReference = map.get(key);
 
  if(softReference ==null) {
   returnnull;
  }
  returnsoftReference.get();
 }
 
 publicvoidput(K key, V value) {
  map.put(key,newSoftReference<V>(value));
 }
 
}
ImageLoader.java (WeakReferenceCache) 
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
packagecom.simonefolinojavablog.weakreferencecache;
 
importjava.util.logging.Level;
 
publicclassImageLoader {
 
 privatestaticWeakReferenceCache<String, ValueCache> cache =newWeakReferenceCache<String, ValueCache>();
 
 publicstaticValueCache 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 =newValueCache();
   newValue.setKey(key);
   cache.put(key, newValue);
   result = newValue;
  }else{
   ProjectLogger.PROJECT_LOGGER.getLogger().log(Level.INFO,"entry: "+ key +" result: cache hit");
 
  }
  returnresult;
 }
 
}

WeakReferenceCache.java 
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
packagecom.simonefolinojavablog.weakreferencecache;
 
importjava.lang.ref.WeakReference;
importjava.util.HashMap;
 
publicclassWeakReferenceCache<KextendsComparable<K>, V> {
 
 privateHashMap<K, WeakReference<V>> map =newHashMap<K, WeakReference<V>>();
  
 publicV get(K key) {
 
  WeakReference<V> WeakReference = map.get(key);
 
  if(WeakReference ==null) {
   returnnull;
  }
  returnWeakReference.get();
 }
 
 publicvoidput(K key, V value) {
  map.put(key,newWeakReference<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
相關文章
相關標籤/搜索