Vous avez besoin de deux cartes: l'une des cartes entre le cache de la clé et de la faiblesse des référencé valeurs et l'un dans la direction opposée de la cartographie entre la faible référencé valeurs et les touches. Et vous avez besoin d'une référence de la file d'attente et un thread de nettoyage.
Références faibles ont la capacité de déplacer la référence dans une file d'attente lorsque l'objet référencé ne peut pas accéder plus longtemps. Cette file d'attente doit être évacuée par un thread de nettoyage. Et pour le nettoyage, il est nécessaire d'obtenir la clé pour une référence. C'est la raison pour laquelle la deuxième carte est nécessaire.
L'exemple suivant montre comment créer un cache avec un hachage de la carte de références faibles. Lorsque vous exécutez le programme, vous obtenez le résultat suivant:
$ javac -Xlint:décoché Cache.java && Cache de java
{même: [2, 4, 6], bizarre: [1, 3, 5]}
{même: [2, 4, 6]}
La première ligne affiche le contenu du cache avant de la référence à l'étrange liste a été supprimé et la deuxième ligne, après que les chances ont été supprimés.
C'est le code:
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
class Cache<K,V>
{
ReferenceQueue<V> queue = null;
Map<K,WeakReference<V>> values = null;
Map<WeakReference<V>,K> keys = null;
Thread cleanup = null;
Cache ()
{
queue = new ReferenceQueue<V>();
keys = Collections.synchronizedMap (new HashMap<WeakReference<V>,K>());
values = Collections.synchronizedMap (new HashMap<K,WeakReference<V>>());
cleanup = new Thread() {
public void run() {
try {
for (;;) {
@SuppressWarnings("unchecked")
WeakReference<V> ref = (WeakReference<V>)queue.remove();
K key = keys.get(ref);
keys.remove(ref);
values.remove(key);
}
}
catch (InterruptedException e) {}
}
};
cleanup.setDaemon (true);
cleanup.start();
}
void stop () {
cleanup.interrupt();
}
V get (K key) {
return values.get(key).get();
}
void put (K key, V value) {
WeakReference<V> ref = new WeakReference<V>(value, queue);
keys.put (ref, key);
values.put (key, ref);
}
public String toString() {
StringBuilder str = new StringBuilder();
str.append ("{");
boolean first = true;
for (Map.Entry<K,WeakReference<V>> entry : values.entrySet()) {
if (first)
first = false;
else
str.append (", ");
str.append (entry.getKey());
str.append (": ");
str.append (entry.getValue().get());
}
str.append ("}");
return str.toString();
}
static void gc (int loop, int delay) throws Exception
{
for (int n = loop; n > 0; n--) {
Thread.sleep(delay);
System.gc(); // <- obstinate donkey
}
}
public static void main (String[] args) throws Exception
{
// Create the cache
Cache<String,List> c = new Cache<String,List>();
// Create some values
List odd = Arrays.asList(new Object[]{1,3,5});
List even = Arrays.asList(new Object[]{2,4,6});
// Save them in the cache
c.put ("odd", odd);
c.put ("even", even);
// Display the cache contents
System.out.println (c);
// Erase one value;
odd = null;
// Force garbage collection
gc (10, 10);
// Display the cache again
System.out.println (c);
// Stop cleanup thread
c.stop();
}
}