weakreference - ¿Por qué necesitamos una referencia débil en java?
weak reference android (8)
Entiendo que las referencias débiles están a merced del recolector de basura, y no podemos garantizar que la referencia débil exista. No podía ver la necesidad de tener una referencia débil, pero seguro que debería haber una razón.
- ¿Por qué necesitamos una referencia débil en java?
- ¿Cuáles son los usos prácticos (algunos) de la referencia débil en java? ¡Si puedes compartir cómo lo usaste en tu proyecto, será genial!
Desacoplamiento de pub-sub o bus de eventos
Una WeakReference
es buena cuando desea que un objeto se dirija a la recolección de basura sin tener que eliminarse con gracia de otros objetos que tengan una referencia.
En escenarios tales como publish-subscribe o un bus de eventos, se mantiene una colección de referencias a objetos suscritos. Esas referencias deben ser débiles, de modo que el suscriptor pueda salir convenientemente del ámbito sin molestarse en darse de baja. El suscriptor puede simplemente "desaparecer" después de que todos los demás lugares en la aplicación hayan publicado su fuerte referencia. En ese momento, no es necesario que la lista de suscripciones o el bus de eventos sigan colgando del suscriptor. El uso de WeakReference
permite que el objeto continúe su camino hacia el olvido.
El objeto suscriptor puede haber sido suscrito sin su conocimiento, enviado al pub-sub o al bus de eventos por algún otro objeto de terceros. Coordinar una llamada para cancelar la suscripción más adelante en el ciclo de vida del suscriptor puede ser bastante engorroso. Por lo tanto, dejar que el suscriptor desaparezca sin anular la suscripción formalmente puede simplificar enormemente su código, y puede evitar errores difíciles si esa coordinación de anulación de la suscripción fallara.
Este es un ejemplo de un conjunto seguro de subprocesos de referencias débiles, como se ve en esta Respuesta y esta Respuesta .
this.subscribersSet =
Collections.synchronizedSet(
Collections.newSetFromMap(
new WeakHashMap <>()
)
);
Tenga en cuenta que la entrada en el conjunto no se elimina realmente hasta después de que la recolección de basura se ejecute realmente, como se explicó en la Respuesta vinculada anterior. Si bien existe como candidato para la recolección de basura (no quedan referencias sólidas en ningún lugar), el elemento permanece en el conjunto.
Digamos que necesita mantener cierta información siempre que se haga referencia a un objeto, pero no sabe cuándo desaparecerá, puede usar una referencia débil para realizar un seguimiento de la información.
En realidad, a menudo es una mala idea usar hashmaps débiles. Por un lado, es fácil equivocarse, pero lo que es peor, generalmente se usa para implementar algún tipo de caché.
Lo que esto significa es lo siguiente: su programa funciona bien con un buen rendimiento durante algún tiempo, bajo el estrés asignamos más y más memoria (más solicitudes = más presión de memoria = probablemente más entradas de caché) que luego conduce a un GC.
Ahora, de repente, mientras su sistema está bajo un alto nivel de estrés, no solo obtiene el GC, sino que también pierde su caché completo, justo cuando más lo necesita. No es divertido este problema, por lo que al menos tiene que usar un caché LRU de tamaño razonable y referenciado para mitigar ese problema; aún puede usar los puntos débiles débiles pero solo como una ayuda adicional.
He visto más de un proyecto golpeado por ese "error" ..
La razón principal por la que uso referencias débiles es indirectamente, a través de un WeakHashMap.
Es posible que desee almacenar una colección de objetos en un Mapa (como caché o por cualquier otro motivo), pero no desea que estén en la memoria mientras exista el Mapa, especialmente si los objetos son relativamente grandes.
Al usar un WeakHashMap, puede asegurarse de que la referencia del Mapa no sea lo único que mantiene el objeto en la memoria, ya que se recolectará como basura si no existe ninguna otra referencia.
Sí y tiene buen impacto.
Ejemplo del problema del " número de serie del widget " anterior, lo más fácil es utilizar la clase
WeakHashMap
.WeakHashMap
funciona exactamente comoHashMap
, excepto que se hace referencia a las claves (¡no a los valores!) Usando referencias débiles. Si una claveWeakHashMap
convierte en basura, su entrada se elimina automáticamente. Esto evita los escollos que describí y no requiere más cambios que el cambio deHashMap
aWeakHashMap
. Si está siguiendo la convención estándar de referirse a sus mapas a través de la interfaz delMap
, ningún otro código debe ser consciente del cambio.
Se necesitan objetos de referencia débiles para la plataforma JVM para garantizar medios contra las fugas de memoria.
Como deben saber los desarrolladores de Java, Java puede filtrarse, más de lo esperado. Esta afirmación es particularmente cierta en aquellos casos en los que ya no se usa un Objeto, pero alguna colección aún tiene una fuerte referencia a esa instancia: un ejemplo muy simple pero recurrente de pérdida de memoria, de hecho, esa área de memoria no se desasignará hasta que exista la referencia segura.
En el caso anterior, un objeto de referencia débil en la colección asegura que: sin una cadena de referencias fuerte, pero con solo cadenas débiles, la instancia puede ser eliminada como garbace coleccionable.
En mi opinión, todas las características proporcionadas por la Plataforma Java son útiles hasta cierto punto: un programador muy hábil puede hacer que Java sea rápido y confiable, ya que C ++ escribe código de muy alta calidad.
Se requiere hacer determinista la recolección de basura Java . (Desde el punto de vista ligeramente satírico con algo de verdad).
El uso más "inequívocamente sensible" de las referencias débiles que he visto es Guava''s Striped
, que hace rayas de bloqueo. Básicamente, si ningún subproceso tiene actualmente una referencia a una variable de bloqueo, entonces no hay razón para mantener ese bloqueo, ¿verdad? Ese candado podría haberse usado en el pasado, pero ahora no es necesario.
Si tuviera que dar una regla para cuándo usarla, diría que las referencias blandas son preferibles cuando podría usar algo en el futuro, pero podría volver a calcularlo si realmente lo necesitara; Las referencias débiles son especialmente preferibles cuando puede estar seguro de que el valor nunca será necesario después de que una referencia se quede sin memoria. (Por ejemplo, si usa la igualdad de referencia predeterminada para una implementación de equals(Object)
a un tipo de clave de mapa y el objeto deja de ser referenciado en cualquier otro lugar, entonces puede estar seguro de que nunca se volverá a hacer referencia a la entrada.