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ó?

¿Fue útil?

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

  1. Proyecto Apache xbean: WeakHashMapEditor.java
  2. 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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top