¿Cuándo utilizaría un WeakHashMap o un WeakReference?
-
03-07-2019 - |
Pregunta
El uso de referencias débiles es algo de lo que nunca he visto una implementación, así que estoy tratando de averiguar cuál es el caso de uso para ellos y cómo funcionaría la implementación. ¿Cuándo ha necesitado usar un WeakHashMap
o WeakReference
y cómo se usó?
Solución
Un problema con referencias fuertes es almacenamiento en caché, en particular con muy grande Estructuras como imágenes. Supongamos que usted Tiene una aplicación que tiene que funcionar. con imágenes suministradas por el usuario, como la Herramienta de diseño de sitio web en la que trabajo. Naturalmente, usted quiere almacenar estos Imágenes, porque cargándolas desde el disco. es muy caro y quieres Evitar la posibilidad de tener dos. copias de la (potencialmente gigantesca) Imagen en memoria a la vez.
Porque se supone que un caché de imagen nos impide recargar imágenes cuando No necesitamos absolutamente, lo harás Rápidamente darse cuenta de que el caché debe siempre contienen una referencia a cualquier Imagen que ya está en memoria. Con referencias fuertes ordinarias, sin embargo, esa referencia obligará a la Imagen para permanecer en la memoria, que te obliga a determinar de alguna manera cuando la imagen ya no es necesaria en Memoria y eliminarlo de la caché, para que sea elegible para recolección de basura. Estás obligado a duplicar el comportamiento de la basura recolector y determinar manualmente si un objeto debe o no estar en memoria.
Cómo entender las referencias débiles , Ethan Nicholas
Otros consejos
Una distinción que se debe aclarar es la diferencia entre una WeakReference
y una SoftReference
.
Básicamente, una WeakReference
será GC-d con entusiasmo por la JVM, una vez que el objeto al que se hace referencia no tenga referencias difíciles a él. Un objeto SoftReference
d por otro lado, tenderá a ser dejado por el recolector de basura hasta que realmente necesite reclamar la memoria.
Un caché donde los valores se mantienen dentro de WeakReference
s sería bastante inútil (en un WeakHashMap
, son las claves las que están débilmente referenciado). SoftReferences
son útiles para envolver los valores cuando se desea implementar un caché que puede aumentar y disminuir con la memoria disponible
Un uso común de WeakReference
y WeakHashMap
en particular es para agregar propiedades a los objetos. Ocasionalmente, desea agregar alguna funcionalidad o datos a un objeto, pero la subclase y / o la composición no son una opción en ese caso, lo obvio sería crear un hashmap que vincule el objeto que desea extender a la propiedad que desea agregar. . Luego, cuando necesite la propiedad, puede buscarla en el mapa. Sin embargo, si los objetos a los que está agregando propiedades tienden a destruirse y crearse mucho, puede terminar con muchos objetos antiguos en su mapa que ocupan mucha memoria.
Si usa un WeakHashMap
, los objetos abandonarán su mapa tan pronto como el resto de su programa ya no los utilice, lo cual es el comportamiento deseado.
Tuve que hacer esto para agregar algunos datos a java.awt.Component
para evitar un cambio en el JRE entre 1.4.2 y 1.5, podría haberlo solucionado subclasificando cada componente I estaba interesado en int ( JButton
, JFrame
, JPanel
....) pero esto fue mucho más fácil con mucho menos código.
Otro caso útil para WeakHashMap
y WeakReference
es una implementación del registro de oyentes .
Cuando creas algo que quiere escuchar ciertos eventos, generalmente registras a un oyente, por ejemplo,
manager.registerListener(myListenerImpl);
Si el manager
almacena a su oyente con una WeakReference
, eso significa que no es necesario eliminar el registro, por ejemplo. con un manager.removeListener (myListenerImpl)
porque se eliminará automáticamente una vez que su oyente o su componente que contiene al oyente no esté disponible.
Por supuesto, aún puede eliminar manualmente su escucha, pero si no lo hace o si lo olvida, no provocará una pérdida de memoria y no evitará que se recoja la basura de su oyente.
¿Dónde aparece WeakHashMap
en la imagen?
El registro de oyentes que desea almacenar oyentes registrados como WeakReference
s necesita una colección para almacenar estas referencias. No hay implementación WeakHashSet
en la biblioteca estándar de Java, solo una WeakHashMap
, pero podemos usar fácilmente la última para " implementar " la funcionalidad del primero:
Set<ListenerType> listenerSet =
Collections.newSetFromMap(new WeakHashMap<ListenerType, Boolean>());
Con este listenerSet
para registrar un nuevo oyente, solo tiene que agregarlo al conjunto, e incluso si no se elimina explícitamente, si ya no se hace referencia al oyente, se eliminará automáticamente. por la JVM.
Esta publicación de blog demuestra el uso de ambas clases: Java: sincronizando en una ID . El uso es algo como esto:
private static IdMutexProvider MUTEX_PROVIDER = new IdMutexProvider();
public void performTask(String resourceId) {
IdMutexProvider.Mutex mutext = MUTEX_PROVIDER.getMutex(resourceId);
synchronized (mutext) {
// look up the resource and do something with it
}
}
IdMutextProvider proporciona objetos basados ??en id para sincronizar. Los requisitos son:
- debe devolver una referencia al mismo objeto para el uso simultáneo de ID equivalentes
- debe devolver un objeto diferente para diferentes ID
- mecanismo de liberación (los objetos no se devuelven al proveedor)
- no debe filtrarse (los objetos no utilizados son elegibles para la recolección de basura)
Esto se logra mediante un mapa de almacenamiento interno de tipo:
WeakHashMap<Mutex, WeakReference<Mutex>>
El objeto es clave y valor. Cuando nada externo al mapa tiene una referencia dura al objeto, puede ser recolectado como basura. Los valores en el mapa se almacenan con referencias firmes, por lo que el valor debe estar envuelto en una WeakReference para evitar una pérdida de memoria. Este último punto se trata en javadoc .
Si, por ejemplo, desea realizar un seguimiento de todos los objetos creados de una determinada clase. Para seguir permitiendo que estos objetos se recojan, se mantiene una lista / mapa de referencias débiles a los objetos en lugar de los objetos en sí.
Ahora, si alguien me pudiera explicar las referencias fantasma, sería feliz ...
Como se indicó anteriormente, las referencias débiles se mantienen mientras exista una referencia sólida.
Un ejemplo de uso sería usar WeakReference dentro de los oyentes, de modo que los oyentes ya no estén activos una vez que la referencia principal a su objeto objetivo haya desaparecido. Tenga en cuenta que esto no significa que se elimine WeakReference de la lista de escuchas, la limpieza aún es necesaria pero se puede realizar, por ejemplo, a horas programadas. Esto también tiene el efecto de evitar que el objeto escuchado contenga referencias sólidas y eventualmente sea una fuente de expansión de memoria. Ejemplo: los componentes de la GUI de Swing que hacen referencia a un modelo que tiene un ciclo de vida más largo que la ventana.
Mientras jugamos con oyentes como se describe anteriormente, nos dimos cuenta rápidamente de que los objetos se recolectan " inmediatamente " desde el punto de vista de un usuario.
Un uso del mundo real que tuve para WeakReferences es si tienes un objeto muy grande que rara vez se usa. No querrás tenerlo en la memoria cuando no sea necesario; pero, si otro subproceso necesita el mismo objeto, tampoco querrá dos de ellos en la memoria. Puede mantener una referencia débil al objeto en alguna parte, y referencias duras en los métodos que lo utilizan; cuando los dos métodos terminen, el objeto será recogido.
Hice una búsqueda en el código de Google para " nuevo WeakHashMap () " ;.
Obtuve un montón de coincidencias del proyecto classpath de GNU y
- Proyecto Apache xbean: WeakHashMapEditor.java
- Proyecto Apache Lucene: CachingWrapperFilter.java
puede usar weakhashmap para implementar un almacenamiento en caché sin recursos para la creación de objetos expansivos.
pero tenga en cuenta que no es deseable tener objetos mutables. Lo utilicé para almacenar en caché los resultados de la consulta (que tardan unos 400 ms en ejecutarse) en un motor de búsqueda de texto, que rara vez se actualiza.