Pregunta

He utilizado LinkedHashMap con accessOrder la verdadera junto con permitir un máximo de 500 entradas en cualquier momento como la LRU de caché para los datos.Pero debido a problemas de escalabilidad quiero pasar a algunos subprocesos alternativos. ConcurrentHashMap parece buena en ese sentido, pero carece de las características de accessOrder y removeEldestEntry(Map.Entry e) se encuentra en LinkedHashMap.¿Alguien puede apuntar a algún tipo de vínculo o me ayudan a facilitar la implementación.

¿Fue útil?

Solución

Yo hice algo similar recientemente con ConcurrentHashMap<String,CacheEntry>, donde CacheEntry envuelve el elemento real y añade caché de desalojo de las estadísticas:el tiempo de caducidad, la inserción de tiempo (por FIFO/LIFO desalojo), utilizó por última vez (por LRU/MRU desalojo), número de visitas (para LFU/MFU desalojo), etc.El real desalojo se sincroniza y crea un ArrayList<CacheEntry> y lo hace de una de las Colecciones.sort() utilizando el Comparador apropiado para el desalojo de la estrategia.Ya que esto es caro, cada desalojo, a continuación, lops fuera de la parte inferior del 5% de la CacheEntries.Estoy seguro de que la optimización del rendimiento sería de ayuda, aunque.

En su caso, ya que estamos haciendo FIFO, se podría mantener una separada ConcurrentLinkedQueue.Cuando se agrega un objeto a la ConcurrentHashMap, hacer un ConcurrentLinkedQueue.add() de ese objeto.Cuando quiere desalojar una entrada, hacer un ConcurrentLinkedQueue.poll() para eliminar los más antiguos objeto, a continuación, retírelo de la ConcurrentHashMap así.

Actualización:Otras posibilidades en esta área incluyen Colecciones Java la sincronización de contenedor y el Java 1.6 ConcurrentSkipListMap.

Otros consejos

¿Has intentado usar una de las muchas soluciones de almacenamiento en caché como ehcache? Puede intentar usar LinkedHashMap con un ReadWriteLock. Esto le daría acceso de lectura concurrente.

Esto puede parecer viejo, pero al menos sólo para mi propio historial de seguimiento, voy a añadir mi solución aquí:He combinado ConcurrentHashMap que los mapas K->subclase de WeakReference, ConcurrentLinkedQueue, y una interfaz que define la serialización de los objetos de valor basado en K para ejecutar LRU almacenamiento en caché correctamente.La cola tiene fuertes referencias, y el GC se desalojar a los valores de la memoria cuando sea apropiado.El seguimiento del tamaño de la cola de los involucrados AtomicInteger, como realmente no se puede inspeccionar la cola para determinar cuando a desalojar.La memoria caché puede manejar el desalojo de/agregar a la cola, así como de la gestión del mapa.Si la GC desalojado el valor de la memoria, la aplicación de la deserialización de la interfaz de la manija de recuperar el valor de la espalda.Yo también tenía otra aplicación que implicó la puesta en cola de disco/re-leer lo que estaba en cola, pero que era mucho más lento que la solución que he publicado aquí, como Ihad para sincronizar la cola de lectura.

Usted menciona querer resolver problemas de escalabilidad con un " thread-safe " alternativa. " Seguridad del hilo " aquí significa que la estructura es tolerante de los intentos de acceso concurrente, ya que no sufrirá corrupción por el uso concurrente sin sincronización externa. Sin embargo, dicha tolerancia no necesariamente ayuda a mejorar & Quot; escalabilidad & Quot ;. En el enfoque más simple, aunque generalmente equivocado, tratará de sincronizar su estructura internamente y dejará las operaciones no atómicas check-then-act inseguras.

Las memorias caché LRU requieren al menos cierta conciencia de la estructura total. Necesitan algo como un recuento de los miembros o el tamaño de los miembros para decidir cuándo desalojar, y luego deben poder coordinar el desalojo con intentos concurrentes de leer, agregar o eliminar elementos. Intentando reducir la sincronización necesaria para el acceso concurrente a & Quot; main & Quot; estructura lucha contra su mecanismo de desalojo y obliga a su política de desalojo a ser menos precisa en sus garantías.

La respuesta actualmente aceptada menciona " cuando desea desalojar una entrada " ;. Ahí está el problema. ¿Cómo sabes cuándo quieres desalojar una entrada? ¿Qué otras operaciones necesita pausar para tomar esta decisión?

Envuelva el mapa en un Collections.synchronizedMap(). Si necesita llamar a métodos adicionales, entonces synchronize en el mapa que recibió de esta llamada e invoque el método original en el mapa original ( vea los javadocs para ver un ejemplo ). Lo mismo se aplica cuando itera sobre las teclas, etc.

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