2009-02-22 2 views
70

Sto cercando una semplice cache in memoria Java con una buona concorrenza (quindi LinkedHashMap non è abbastanza buona) e che può essere serializzata su disco periodicamente.Alla ricerca di una semplice cache in memoria Java

Una funzione di cui ho bisogno, ma che è stato difficile trovare, è un modo per "sbirciare" su un oggetto. Con questo intendo il recupero di un oggetto dalla cache senza che la cache rimanga sull'oggetto più a lungo di quanto non avrebbe altrimenti.

Aggiornamento: Un ulteriore requisito che ho dimenticato di menzionare è che devo essere in grado di modificare gli oggetti memorizzati nella cache (contengono matrici mobili) sul posto.

Qualcuno può fornire qualche suggerimento?

+1

Sto cercando qualcosa di simile che è "all'interno del processo" e il peso più leggero. Voglio usarlo per memorizzare alcuni dati all'interno di un plugin Eclipse nell'heap. Ehcache e JCS sembrano troppo pesanti/distribuiti/J2EE per i miei gusti. – Uri

+1

possibile duplicato di [Lightweight Java cache cache API] (http://stackoverflow.com/questions/230649/lightweight-java-object-cache-api) – Raedwald

risposta

45

Dal momento che questa domanda è stato originariamente chiesto, Google's Guava library include ora una cache potente e flessibile. Consiglierei di usare questo.

34

Ehcache è una bella buona soluzione per questo e ha un modo di sbirciare (getQuiet() è il metodo) in modo tale che non aggiorna il timestamp inattivo. Internamente, Ehcache è implementato con una serie di mappe, un po 'come ConcurrentHashMap, quindi ha simili vantaggi di concorrenza.

+2

Grazie, una domanda aggiuntiva: se recupero un oggetto da EHcache (ad esempio un array) e lo modifico, l'oggetto verrà aggiornato nella cache? vale a dire. EHCache mantiene i riferimenti agli oggetti? – sanity

+1

Credo di sì, ma per farlo in sicurezza devi bloccare l'oggetto in modo appropriato, ovviamente. –

0

Provare Ehcache? Ti consente di collegare i tuoi algoritmi di scadenza del caching in modo da poter controllare la tua funzionalità di sbirciatina.

È possibile serializzare su disco, banca dati, attraverso un cluster ecc ...

14

Se stai bisogno di qualcosa di semplice, sarebbe questa misura la fattura?

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

E 'abitudine salvare su disco, ma hai detto che volevi semplice ...

vicini:

(Come ha commentato Adam, la sincronizzazione di una mappa ha un impatto sulle prestazioni. Non dire che l'idea non abbia i capelli su di me t, ma sarebbe sufficiente come una soluzione rapida e sporca)

+2

La sincronizzazione di un'intera gigantesca mappa è una pesante punizione. È possibile memorizzare facilmente i tipi deboli in una mappa hash simultanea e rimuoverli periodicamente. –

+3

ConcurrentHashMap è migliore di Collections.synchronizedMap http://stackoverflow.com/questions/6692008/java-concurrenthashmap-is-better-than-hashmap-performance-wise –

+6

Per quanto riguarda le prestazioni, ConcurrentHashMap offre prestazioni migliori, ma non condividere le proprietà di una WeakHashMap per consentire al garbage collector di recuperare memoria. Questo può o non può essere importante per te. – Evan

9

Prova questa:.

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

I problemi relativi all'utilizzo di una mappa sincronizzata erano già stati discussi in altre risposte. – sanity

+0

@sergeyB: stavo cercando una soluzione simile che sia semplice per implementare la cache ... Grazie –

+0

'public static SimpleCacheManager getInstance() {' dovrebbe essere 'public synchronized static SimpleCacheManager getInstance() {' altrimenti 'if (instance == null) {'non è sicuro come thread. In tal caso è possibile rimuovere l'oggetto monitor tutti insieme da quando la sincronizzazione ha luogo per tutte le chiamate getInstance(), vedere: http://www.javaworld.com/article/2073352/core-java/simply-singleton.html?page= 2 –

9

È possibile utilizzare facilmente imcache. Un codice di esempio è sotto.

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

Un'altra opzione per una cache java in memoria è cache2k. Le prestazioni in memoria sono superiori a EHCache e google guava, vedere cache2k benchmarks page.

Il modello di utilizzo è simile ad altre cache.Ecco un esempio:

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"); 

Se si dispone di google guava come dipendenza quindi provare cache di guava, potrebbe essere una buona alternativa.