K
- the type of keys maintained by this mapV
- the type of mapped valuespublic final class WeakValueCache<K,V> extends Object
Note that this class intentionally does not implement the
full Map
interface; It only provides get(K)
,
put(K, V)
and size()
methods.
When an instance of WeakValueCache
is constructed, it requires
a ReferenceQueue
as a parameter. That queue is where the "zombie"
references
will be placed when values are
garbage collected. It is expected that a CacheCleaner
is "attached"
to the queue to automatically remove entries containing zombie references
from the internal map.
These classes were designed this way to allow a common reference queue to be used for related data types, and thus have one common background thread do clean up for a number of caches, rather than one thread per cache.
The recommended usage pattern for these classes is as follows:
Suppose you have 3 datatypes: Type1
, Type2
, Type3
,
for which you want caches. Also suppose they all extend SuperType
.
The SuperType
class is a good place to define the common reference
queue with attached CacheCleaner
:
public abstract class SuperType { // lazily initialized reference queue private static ReferenceQueue<SuperType> refQ; // allow subclasses to retrieve a reference to the queue // first invocation creates and starts the cleaner thread protected static synchronized ReferenceQueue<SuperType> getRefQ() { if (refQ == null) { refQ = new ReferenceQueue<SuperType>(); new CacheCleaner(refQ).start(); } return refQ; } }The datatype classes will look something like this:
public final class Type1 extends SuperType { // private constructor(s) to control instance creation private Type1(final String str) { ... } ... // our self-trimming cache private static final WeakValueCache<String, Type1> cache = new WeakValueCache<String, Type1>(getRefQ()); ... // PUBLIC API: public static Type1 valueOf(final String stringRep) { synchronized (cache) { Type1 t = cache.get(stringRep); if (t == null) { t = new Type1(stringRep); cache.put(stringRep, t); } return t; } // sync } }Note the synchronization on the cache object in the
valueOf
method.
This is necessary to make the "find or create" paradigm "atomic" with
respect to the cache. The CacheCleaner
also synchronizes on the
cache during its work of removing zombie entries.Constructor and Description |
---|
WeakValueCache(ReferenceQueue<? super V> queue)
Constructs an empty weak value map with the specified reference queue
for GC'd value reference housekeeping.
|
Modifier and Type | Method and Description |
---|---|
V |
get(K key)
Returns the value to which the specified key is mapped,
or
null if this map contains no mapping for the key. |
V |
put(K key,
V value)
Associates the specified value with the specified key in this map.
|
int |
size()
Returns the size of the map.
|
public WeakValueCache(ReferenceQueue<? super V> queue)
queue
- the reference queueNullPointerException
- if queue is nullpublic V get(K key)
null
if this map contains no mapping for the key.key
- the keyNullPointerException
- if key is nullpublic V put(K key, V value)
key
- the key with which the specified value is to be associatedvalue
- the value to be associated with the specified keyNullPointerException
- if key or value is nullpublic int size()
Copyright © 2015. All Rights Reserved.