Pregunta

Sé que hay un WeakHashMap en java.util , pero dado que usa WeakReference s para todo, al que solo hace referencia esto Map , los objetos referenciados 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 nuevamente sin estar vinculados el resto del tiempo. La mejor solución sería un mapa, que utiliza SoftReference s en su lugar, pero no encontré uno en el paquete Java RT.

¿Fue útil?

Solución

Editar (agosto de 2012):

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


No es que lo sé (noviembre de 2008), pero usted encuentre alguna implementación de SoftHashMap en la red.

Como este: SoftHashMap SoftHashMap SoftHashMap / a> o este .


Editar (noviembre de 2009)
Como Matthias menciona en los comentarios, el Google Guava MapMaker usa SoftReferences:

  

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

     
      
  • teclas suaves o débiles,
  •   
  • valores blandos o débiles,
  •   
  • caducidad programada y
  •   
  • cálculo de valores bajo demanda.
  •   

Como se menciona en este hilo , otro JSR166y candidato:

jsr166y.ConcurrentReferenceHashMap

  

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


Editar (agosto de 2012)

La implementación de Google usa un hilo de fondo solo cuando se solicita la caducidad 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 función para evitar los peligros de SoftReference: http://jeremymanson.blogspot.de/2009/ 07 / how-hotspot-decide-despejar_07.html

Hay otra implementación de Apache Commons , a saber, org.apache.commons.collections.map.ReferenceMap ; no admite la eliminación programada, pero sí permite elegir si las claves deben compararse por identidad o por igualdad. Además, esta implementación no es concurrente: se puede sincronizar, pero eso funciona menos bien bajo accesos desde múltiples hilos.

Otros consejos

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

Hay un ejemplo de implementación en 98 número del boletín de especialistas de Java

Apache Shiro viene con un SoftHashMap diseñado para el almacenamiento en caché. Se basa en el artículo publicado por jb arriba y con licencia de 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? Obtiene más control sobre lo que se almacena (o al menos, cuánto).

Si desea implementar un caché, las softreferences 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 sea lo que quieres.

Si la política de eliminación de caché es importante, es probable que deba hacerlo por su cuenta utilizando referencias regulares. Sin embargo, tendrá que decidir cuándo expulsar elementos y cuáles expulsar. Si solo desea perder cosas cuando se está quedando sin espacio de almacenamiento dinámico, puede consultar el espacio de almacenamiento dinámico disponible a través de:

Runtime.getRuntime().getFreeMemory();

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

aquí hay un caché LRU Diseñé con O (1) inserción, eliminación y tiempo de búsqueda, que tiene un número máximo de elementos configurables. Si desea un caché, esta será una mejor solución en mi humilde opinión que un SoftHashMap.

Las softreferences son una excelente manera de crear una memoria caché ampliable. Entonces, la solución ideal sería usar un SoftHashMap junto con un caché de tamaño fijo regular. haga que todas las inserciones en la memoria caché entren tanto en la memoria caché fija como en el mapa de hash suave y luego haga referencia a algo solo vea si está en el mapa de hash suave (y actualice el tiempo de referencia en la memoria caché). de esta manera, todos sus elementos más importantes (de acuerdo con la política elegida LRU, MFU, ...) nunca se eliminarán porque están referenciados en la memoria caché, pero también conservará más cosas (sin control de políticas) mientras ya que hay suficiente memoria.

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