2009-02-22 18 views
70

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

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 memoria caché sin hacer que la memoria caché se aferre al objeto más de lo que lo hubiera hecho de otra manera.

Actualización: Un requisito adicional que omití mencionar es que necesito poder modificar los objetos en caché (que contienen matrices flotantes) en el lugar.

¿Alguien puede proporcionar alguna recomendación?

+1

Busco algo similar que está "dentro del proceso" y un peso más ligero. Quiero usarlo para almacenar algunos datos dentro de un plugin de Eclipse en el montón. Ehcache y JCS parecen demasiado pesados ​​/ distribuidos/J2EE para mi gusto. – Uri

+1

posible duplicado de [API ligera de caché de objetos Java] (http://stackoverflow.com/questions/230649/lightweight-java-object-cache-api) – Raedwald

Respuesta

45

Dado que esta pregunta fue hecha en un principio, ahora Google's Guava library incluye un potente y flexible caché. Yo recomendaría usar esto.

34

Ehcache es una muy buena solución para esto y tiene una manera de mirar (getQuiet() es el método) de tal 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 ventajas de concurrencia.

+2

Gracias, una pregunta adicional: si recupero un objeto de EHcache (por ejemplo, una matriz) y lo modifico, ¿se actualizará el objeto en la memoria caché? es decir. ¿EHCache mantiene referencias a los objetos? – sanity

+1

Creo que sí, pero para hacer esto de forma segura, debe bloquear correctamente el objeto, por supuesto. –

0

Probar Ehcache? Le permite conectar sus propios algoritmos de caducidad de caché para que pueda controlar su funcionalidad de peek.

Puede serializar en el disco, base de datos, a través de un cluster, etc ...

14

Si usted está necesitando algo simple, sería esta forma la factura?

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

No lo puedo guardar en el disco, pero dijo que quería sencilla ...

Enlaces:

(como Adam comentó, sincronizar un mapa tiene un impacto en el rendimiento. No decir que la idea no tiene pelos en mi t, pero bastaría como una solución rápida y sucia)

+2

Sincronizar un mapa gigantesco entero es una pena considerable. Puede almacenar fácilmente tipos débiles en un mapa hash concurrente y eliminarlos periódicamente. –

+3

ConcurrentHashMap es mejor que Collections.synchronizedMap http://stackoverflow.com/questions/6692008/java-concurrenthashmap-is-better-than-hashmap-performance-wise –

+6

En cuanto a rendimiento, ConcurrentHashMap tiene un rendimiento absolutamente mejor, pero no lo hace comparta las propiedades de un WeakHashMap con respecto a permitir que el recolector de basura recupere memoria. Esto puede o no ser importante para ti. – Evan

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; 
    } 

} 
+0

Los problemas con depender de un mapa sincronizado ya se discutieron en otras respuestas. – sanity

+0

@sergeyB: Estaba buscando una solución similar que es simple para implementar el caché ... Gracias –

+0

'staticChecheManager staticSearch() {' debe ser 'static synchronized static SimpleCacheManager getInstance() {' otherwise 'if (instance == null) {'no es seguro para subprocesos. En ese caso, puede eliminar el objeto del monitor en conjunto ya que la sincronización se lleva a cabo para todas las llamadas a getInstance(), consulte: http://www.javaworld.com/article/2073352/core-java/simply-singleton.html?page= 2 –

9

Puede usar fácilmente imcache. Un código de muestra está debajo.

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

Otra opción para una memoria caché java en memoria es cache2k. El rendimiento en memoria es superior a EHCache y Google guava, consulte el cache2k benchmarks page.

El patrón de uso es similar a otros cachés.Aquí está 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 de guayaba como la dependencia a continuación, probar caché guayaba, puede ser una buena alternativa.

Cuestiones relacionadas