Buscando caché en memoria de Java simple [cerrado]

102

Estoy buscando un caché en memoria de Java simple que tenga buena concurrencia (por lo que LinkedHashMap no es lo suficientemente bueno) y que se pueda serializar en el disco periódicamente.

Una característica que necesito, pero que ha resultado difícil de encontrar, es una forma de "mirar" un objeto. Con esto me refiero a recuperar un objeto de la caché sin hacer que la caché se aferre al objeto más tiempo del que tendría de otra manera.

Actualización: un requisito adicional que olvidé mencionar es que necesito poder modificar los objetos en caché (contienen matrices flotantes) en su lugar.

¿Alguien puede dar alguna recomendación?

cordura
fuente
1
Estoy buscando algo similar que esté "dentro del proceso" y sea más ligero. Quiero usarlo para almacenar algunos datos dentro de un complemento de Eclipse en el montón. Ehcache y JCS parecen demasiado pesados ​​/ distribuidos / J2EE para mi gusto.
Uri
1
posible duplicado de la API de caché de objetos ligeros de Java
Raedwald
Recomendaré Apache Ignite ( ignite.apache.org )
Bhagat S.
1
Que esta pregunta esté cerrada (6 años después del hecho) y que todavía es algo que la gente se pregunta hoy, muestra cómo está fallando el sistema de moderadores de SO.
dustinevan

Respuestas:

61

Dado que esta pregunta se hizo originalmente, la biblioteca Guava de Google ahora incluye un caché potente y flexible. Recomendaría usar esto.

cordura
fuente
3
Tenga en cuenta que Spring ya no admite la caché de Guava: stackoverflow.com/questions/44175085/…
sinner
@sanity ¿implementa Jcache?
gaurav
Caffine también es una biblioteca de almacenamiento en caché agradable y eficaz . La cafeína es una biblioteca de almacenamiento en caché casi óptima de alto rendimiento basada en Java 8. La cafeína proporciona una caché en la memoria utilizando una API inspirada en Google Guava
Slavus
37

Ehcache es una solución bastante buena para esto y tiene una forma de echar un vistazo ( getQuiet () es el método) de manera que no actualiza la marca de tiempo inactiva. Internamente, Ehcache se implementa con un conjunto de mapas, algo así como ConcurrentHashMap, por lo que tiene tipos similares de beneficios de concurrencia.

Alex Miller
fuente
2
Gracias, una pregunta adicional: si recupero un objeto de EHcache (digamos, una matriz) y lo modifico, ¿el objeto se actualizará en la caché? es decir. ¿EHCache mantiene referencias a los objetos?
cordura
1
Creo que sí, pero para hacer esto de forma segura, por supuesto, debe bloquear adecuadamente el objeto.
Alex Miller
Me encanta ehcache, sin embargo, es un frasco de 10 MB. Demasiado grande.
markthegrea
23

Si necesita algo simple, ¿esto se ajusta a la factura?

Map<K, V> myCache = Collections.synchronizedMap(new WeakHashMap<K, V>());

No se guardará en el disco, pero dijiste que querías simple ...

Enlaces:

(Como comentó Adam, sincronizar un mapa tiene un impacto en el rendimiento. No digo que la idea no tenga pelos en ella, pero sería suficiente como una solución rápida y sucia).

Evan
fuente
4
Sincronizar todo un mapa gigantesco es una gran penalización. Puede almacenar fácilmente tipos débiles en un mapa hash concurrente y eliminarlos periódicamente.
Adam Gent
7
ConcurrentHashMap es mejor que Collections.synchronizedMap stackoverflow.com/questions/6692008/…
Pablo Moretti
8
En cuanto al rendimiento, ConcurrentHashMap tiene un rendimiento absolutamente mejor, pero no comparte las propiedades de un WeakHashMap con respecto a permitir que el recolector de basura reclame memoria. Esto puede ser importante para usted o no.
Evan
4
Entonces usa ConcurrentHashMap<WeakReference<T>>. docs.oracle.com/javase/7/docs/api/java/lang/ref/…
jdmichal
19

Otra opción para un caché de Java en memoria es cache2k . El rendimiento en memoria es superior al de EHCache y google guava, consulte la página de pruebas de rendimiento de cache2k .

El patrón de uso es similar a otros cachés. Aquí hay un ejemplo:

Cache<String,String> cache = new Cache2kBuilder<String, String>() {}
  .expireAfterWrite(5, TimeUnit.MINUTES)    // expire/refresh after 5 minutes
  .resilienceDuration(30, TimeUnit.SECONDS) // cope with at most 30 seconds
                                          // outage before propagating 
                                          // exceptions
  .refreshAhead(true)                       // keep fresh when expiring
  .loader(new CacheLoader<String, String>() {
    @Override
    public String load(final String key) throws Exception {
      return ....;
    }
  })
  .build();
String val = cache.peek("something");
cache.put("something", "hello");
val = cache.get("something");

Si tiene google guava como dependencia, probar el caché de guayaba puede ser una buena alternativa.

cruftex
fuente
cruftex, si cierro mi aplicación la caché destruirá todos los datos registrados o no?
Menai Ala Eddine - Aladdin
10

Puedes usar imcache fácilmente . A continuación se muestra un código de muestra.

void example(){
    Cache<Integer,Integer> cache = CacheBuilder.heapCache().
    cacheLoader(new CacheLoader<Integer, Integer>() {
        public Integer load(Integer key) {
            return null;
        }
    }).capacity(10000).build(); 
}
yusufaytas
fuente
9

Prueba esto:

import java.util.*;

public class SimpleCacheManager {

    private static SimpleCacheManager instance;
    private static Object monitor = new Object();
    private Map<String, Object> cache = Collections.synchronizedMap(new HashMap<String, Object>());

    private SimpleCacheManager() {
    }

    public void put(String cacheKey, Object value) {
        cache.put(cacheKey, value);
    }

    public Object get(String cacheKey) {
        return cache.get(cacheKey);
    }

    public void clear(String cacheKey) {
        cache.put(cacheKey, null);
    }

    public void clear() {
        cache.clear();
    }

    public static SimpleCacheManager getInstance() {
        if (instance == null) {
            synchronized (monitor) {
                if (instance == null) {
                    instance = new SimpleCacheManager();
                }
            }
        }
        return instance;
    }

}
Serhii Bohutskyi
fuente
Los problemas de confiar en un mapa sincronizado ya se discutieron en otras respuestas.
cordura
@sergeyB: Estaba buscando una solución similar que sea simple para implementar el caché ... Gracias
Prakruti Pathik
1
public static SimpleCacheManager getInstance() {debería ser de public synchronized static SimpleCacheManager getInstance() {otra manera if (instance == null) {no es seguro para subprocesos. En cuyo caso, puede eliminar el objeto del monitor todos juntos, ya que la sincronización tiene lugar para todas las llamadas getInstance (), consulte: javaworld.com/article/2073352/core-java/…
Can Kavaklıoğlu
¿Puedo recomendar usar una enumeración para singleton? dzone.com/articles/java-singletons-using-enum
Erk
0

¿Prueba Ehcache ? Le permite conectar sus propios algoritmos de caducidad de almacenamiento en caché para que pueda controlar su funcionalidad de inspección.

Puede serializar en disco, base de datos, en un clúster, etc.

Stephen
fuente