java hashmap weak-references soft-references

¿Hay un SoftHashMap en Java?



weak-references soft-references (6)

Sé que hay un WeakHashMap en java.util, pero dado que usa WeakReferences para todo, al que solo hace referencia este Mapa, los objetos a los que se hace referencia se perderán en el próximo ciclo de GC. Por lo tanto, es casi inútil si desea almacenar en caché datos aleatorios, que es muy probable que se soliciten de nuevo sin estar vinculados duramente el resto del tiempo. La mejor solución sería un mapa, que utiliza SoftReferences, pero no encontré ninguno en el paquete Java RT.



Estoy familiarizado con dos bibliotecas que ofrecen una implementación de SoftHashMap:

  1. Apache Commons : org.apache.commons.collections.map.ReferenceMap

  2. Colecciones de Google : com.google.common.collect.ReferenceMap


Apache Shiro viene con un SoftHashMap diseñado para el almacenamiento en caché. Está basado en el artículo publicado por jb arriba y con licencia bajo Apache v2. Puede encontrar la documentación aquí y el código fuente aquí .


¿Ha considerado usar un LRUMap en lugar de un HashMap suave? Obtienes más control sobre lo que se almacena (o al menos, cuánto).


Editar (agosto de 2012):

Resulta que actualmente la mejor solución probablemente sean las clases de Cache Guava 13.0, explicadas en la Wiki de Guava, eso es lo que voy a usar. Incluso admite la creación de un SoftHashMap (vea CacheBuilder.newBuilder().softKeys() ), pero probablemente no sea lo que usted desea, como explica el experto en Java, Jeremy Manson (a continuación encontrará el enlace).

No es que yo sepa (noviembre de 2008), pero puede encontrar alguna implementación de SoftHashMap en la red.

Como este: SoftHashMap o este .

Editar (noviembre de 2009)
Como Matthias menciona en los comentarios, Google Guava MapMaker sí utiliza SoftReferences:

Un ConcurrentMap proporciona cualquier combinación de estas características:

  • teclas suaves o débiles,
  • valores suaves o débiles,
  • expiración temporizada, y
  • computación a demanda de los valores.

Como se menciona en este hilo , otro candidato JSR166y:

jsr166y.ConcurrentReferenceHashMap

Proporciona un mapa de referencia concurrente alternativo a la implementación de Google (que se basa en un hilo de fondo para desalojar las entradas)

Editar (agosto de 2012)

La implementación de Google utiliza una cadena de fondo solo cuando se solicita la caducidad temporal de las entradas. En particular, simplemente usa java.util.Timer , que no es tan intrusivo como tener un hilo de fondo separado.

Jeremy Manson recomienda, para cualquier caché, usar esta característica para evitar los peligros de SoftReference: http://jeremymanson.blogspot.de/2009/07/how-hotspot-decides-to-clear_07.html

Hay otra implementación de Apache Commons , es decir, org.apache.commons.collections.map.ReferenceMap ; no es compatible con la eliminación temporizada, pero sí permite elegir si las claves se deben comparar por identidad o por igualdad. Además, esta implementación no es simultánea: se puede sincronizar, pero funciona menos en accesos de múltiples hilos.


Si desea implementar un caché, las referencias son definitivamente una mejor idea que las referencias débiles, pero pone toda su política de eliminación de caché en manos del recolector de basura. que probablemente no es lo que quieres

Si la política de eliminación de caché es importante, tendrá que hacerlo por su cuenta, probablemente con referencias regulares. Sin embargo, tendrá que decidir cuándo expulsar los objetos y cuáles expulsar. Si solo quiere perder cosas cuando se está quedando sin espacio en el montón, puede consultar el espacio disponible en el montón mediante:

Runtime.getRuntime().getFreeMemory();

Luego, una vez que la memoria libre cae por debajo de cierta cantidad, puede comenzar a dropear elementos. O simplemente podría implementar un tamaño máximo para el caché y usarlo para decidir cuándo dejar caer cosas.

aquí hay un caché LRU que diseñé con O (1) inserción, eliminación y tiempo de búsqueda, que tiene una cantidad máxima configurable de elementos. Si quiere un caché, esta será una mejor solución que un SoftHashMap.

Las referencias suaves son una excelente manera de crear una memoria caché que se pueda crecer. Entonces, la solución ideal sería usar un SoftHashMap junto con un caché de tamaño fijo regular. hacer que todas las inserciones en la caché vayan tanto a la memoria caché fija como a la asignación de hash suave, para hacer referencia a algo, solo ver si está en la zona hash suave (y actualizar la hora de referencia en la memoria caché). De esta forma, sus elementos más importantes (de acuerdo con la política elegida, LRU, MFU, ...) nunca se eliminarán, ya que se hacen referencia a ellos en la memoria caché, pero también se mantendrán en más cosas (sin control de política) mientras ya que hay suficiente memoria.