java - weakreference android
¿Cuándo utilizarías WeakHashMap o WeakReference? (10)
El uso de referencias débiles es algo que nunca he visto en una implementación, así que estoy tratando de descubrir cuál es el caso de uso para ellos y cómo funcionaría la implementación. ¿Cuándo necesitó utilizar WeakHashMap
o WeakReference
y cómo se usó?
Un problema con las referencias fuertes es el almacenamiento en caché, en particular con estructuras muy grandes como imágenes. Supongamos que tiene una aplicación que tiene que funcionar con imágenes proporcionadas por el usuario, como la herramienta de diseño de sitios web en la que trabajo. Naturalmente, desea almacenar en caché estas imágenes, ya que cargarlas desde el disco es muy caro y desea evitar la posibilidad de tener dos copias de la imagen (potencialmente gigantesca) en la memoria a la vez.
Como se supone que una memoria caché de imágenes nos impide recargar imágenes cuando no las necesitamos, se dará cuenta rápidamente de que la memoria caché siempre debe contener una referencia a cualquier imagen que ya esté en la memoria. Sin embargo, con referencias fuertes ordinarias, esa referencia forzará a la imagen a permanecer en la memoria, lo que requiere que determine de alguna manera cuándo la imagen ya no se necesita en la memoria y la elimine de la memoria caché para que sea elegible para la recolección de basura. Se ve obligado a duplicar el comportamiento del recolector de elementos no utilizados y determinar manualmente si un objeto debe estar o no en la memoria.
Comprensión de las referencias débiles , Ethan Nicholas
Como se indicó anteriormente, la referencia débil se mantiene mientras exista una referencia fuerte.
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 la WeakReference se elimine de la lista de oyentes, todavía se requiere limpieza, pero puede realizarse, por ejemplo, en horarios programados. Esto también tiene el efecto de evitar que el objeto escuchado contenga referencias fuertes y, finalmente, ser una fuente de saturación de memoria. Ejemplo: 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 jugaba con los oyentes como se describió anteriormente nos dimos cuenta rápidamente de que los objetos se recogen "inmediatamente" desde el punto de vista del usuario.
Esta publicación de blog demuestra el uso de ambas clases: Java: sincronización 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
- sin mecanismo de liberación (los objetos no se devuelven al proveedor)
- no debe tener fugas (los objetos no utilizados son elegibles para la recolección de basura)
Esto se logra usando 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 difícil al objeto, puede ser basura recolectada. Los valores en el mapa se almacenan con referencias duras, por lo que el valor debe estar envuelto en una WeakReference para evitar una pérdida de memoria. Este último punto está cubierto en el javadoc .
Hice una búsqueda de código de google para "nuevo WeakHashMap ()".
Obtuve un montón de coincidencias del proyecto GNU classpath y
- Proyecto Apache xbean: WeakHashMapEditor.java
- Proyecto Apache Lucene: CachingWrapperFilter.java
Otro caso útil para WeakHashMap
y WeakReference
es la implementación de un registro de escucha .
Cuando creas algo que quiere escuchar ciertos eventos, generalmente registras un oyente, por ej.
manager.registerListener(myListenerImpl);
Si el manager
almacena su oyente con una WeakReference
, eso significa que no necesita 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 el oyente no estén disponibles.
Por supuesto, aún puede eliminar manualmente su oyente, pero si no lo hace o lo olvida, no causará una pérdida de memoria, y no evitará que su oyente sea recolectado.
¿Dónde entra WeakHashMap
en la imagen?
El registro de escucha que desea almacenar oyentes registrados como WeakReference
necesita una colección para almacenar estas referencias. No hay implementación WeakHashSet
en la biblioteca Java estándar solo WeakHashMap
pero podemos usar fácilmente la última para "implementar" la funcionalidad de la primera:
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, la JVM lo eliminará automáticamente.
Si, por ejemplo, desea realizar un seguimiento de todos los objetos creados de una determinada clase. Para permitir aún que estos objetos sean basura, se mantiene una lista / mapa de referencias débiles a los objetos en lugar de los objetos mismos.
Ahora si alguien pudiera explicarme referencias fantasmas, estaría feliz ...
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 creación de subclases y / o la composición no son una opción; en ese caso, lo más obvio sería crear un hashmap que vincule el objeto que desea extender con 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 viejos en el mapa que ocupan mucha memoria.
Si utiliza un WeakHashMap
los objetos saldrán de su mapa tan pronto como ya no sean utilizados por el resto de su programa, que es el comportamiento deseado.
Tuve que hacer esto para agregar algunos datos a java.awt.Component
para java.awt.Component
un cambio en el JRE entre 1.4.2 y 1.5, lo podría haber arreglado JButton
cada componente que estaba interesado int ( JButton
, JFrame
, JPanel
. ...) pero esto fue mucho más fácil con mucho menos código.
Un uso del mundo real que tuve para WeakReferences es si tienes un solo objeto muy grande que rara vez se usa. No desea mantenerlo en la memoria cuando no es necesario; pero, si otro hilo necesita el mismo objeto, tampoco quieres dos de ellos en la memoria. Puede mantener una referencia débil al objeto en alguna parte, y referencias difíciles en los métodos que lo usan; cuando los métodos terminen, el objeto será recolectado.
Una distinción que debe ser clara es la diferencia entre una WeakReference
y una SoftReference
.
Básicamente, una WeakReference
hará una WeakReference
con entusiasmo, una vez que el objeto al que se hace referencia no tenga referencias duras . SoftReference
otro lado, un objeto d SoftReference
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
sería bastante inútil (en un WeakHashMap
, son las claves las que están débilmente referenciadas). SoftReferences
son útiles para ajustar los valores cuando se desea implementar un caché que puede crecer y reducirse con la memoria disponible
puede usar weakhashmap para implementar un caché libre de recursos para la creación de objetos expansivos.
pero tenga en cuenta que no es deseable tener objetos mutables. Lo usé para almacenar en caché los resultados de las consultas (que tardan unos 400 ms en ejecutarse) en un motor de búsqueda de texto, que rara vez se actualiza.