Ricerca di una semplice cache in memoria Java [chiusa]


102

Sto cercando una semplice cache in memoria Java che abbia una buona concorrenza (quindi LinkedHashMap non è abbastanza buona) e che possa essere serializzata periodicamente su disco.

Una caratteristica di cui ho bisogno, ma che si è rivelata difficile da trovare, è un modo per "sbirciare" un oggetto. Con questo intendo recuperare un oggetto dalla cache senza far sì che la cache rimanga sull'oggetto più a lungo di quanto avrebbe altrimenti.

Aggiornamento: un ulteriore requisito che ho trascurato di menzionare è che devo essere in grado di modificare gli oggetti memorizzati nella cache (contengono array float) sul posto.

Qualcuno può fornire consigli?


1
Sto cercando qualcosa di simile che sia "all'interno del processo" e più leggero. Voglio usarlo per archiviare alcuni dati all'interno di un plug-in Eclipse nell'heap. Ehcache e JCS sembrano troppo pesanti / distribuiti / J2EE per i miei gusti.
Uri


Raccomanderò Apache Ignite ( ignite.apache.org )
Bhagat S.

1
Che questa domanda sia chiusa (6 anni dopo il fatto) e che ancora oggi le persone si chiedano, mostra come il sistema moderatore di SO stia fallendo.
dustinevan

Risposte:


61

Poiché questa domanda è stata inizialmente posta, la libreria Guava di Google ora include una cache potente e flessibile. Consiglierei di usarlo.


3
Si prega di notare che la primavera non supporta più la cache Guava: stackoverflow.com/questions/44175085/…
peccatore

@sanity implementa Jcache?
Gaurav

Caffine è anche una bella e performante libreria per il caching. Caffeine è una libreria di memorizzazione nella cache ad alte prestazioni e quasi ottimale basata su Java 8. Caffeine fornisce una cache in memoria utilizzando un'API ispirata a Google Guava
Slavus

37

Ehcache è una soluzione abbastanza buona per questo e ha un modo per sbirciare ( getQuiet () è il metodo) in modo tale da non aggiornare il timestamp di inattività. Internamente, Ehcache è implementato con un set di mappe, un po 'come ConcurrentHashMap, quindi ha tipi simili di vantaggi di concorrenza.


2
Grazie, un'ulteriore domanda: se recupero un oggetto da EHcache (ad esempio, un array) e lo modifico, l'oggetto verrà aggiornato nella cache? cioè. EHCache mantiene i riferimenti agli oggetti?
sanità mentale

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

Adoro l'ehcache, tuttavia, è un barattolo da 10 MB. Troppo grande.
markthegrea

23

Se hai bisogno di qualcosa di semplice, questo andrebbe bene?

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

Non salverà su disco, ma hai detto che volevi semplice ...

Collegamenti:

(Come ha commentato Adam, la sincronizzazione di una mappa ha un calo delle prestazioni. Non sto dicendo che l'idea non ha peli su di essa, ma sarebbe sufficiente come soluzione rapida e sporca.)


4
La sincronizzazione di un'intera mappa gigantesca è una pesante penalità. È possibile memorizzare facilmente i tipi deboli in una mappa hash simultanea e rimuoverli periodicamente.
Adam Gent

7
ConcurrentHashMap è migliore di Collections.synchronizedMap stackoverflow.com/questions/6692008/…
Pablo Moretti

8
Dal punto di vista delle prestazioni, ConcurrentHashMap funziona assolutamente meglio, ma non condivide le proprietà di una WeakHashMap per quanto riguarda il consentire al garbage collector di recuperare la memoria. Questo può o non può essere importante per te.
Evan

4
Quindi usa ConcurrentHashMap<WeakReference<T>>. docs.oracle.com/javase/7/docs/api/java/lang/ref/…
jdmichal

19

Un'altra opzione per una java cache in memoria è cache2k . Le prestazioni in memoria sono superiori a EHCache e google guava, vedere la pagina dei benchmark di cache2k .

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 hai google guava come dipendenza, provare guava cache, potrebbe essere una buona alternativa.


cruftex, se chiudo la mia applicazione la cache distruggerà tutti i dati registrati o no?
Menai Ala Eddine - Aladdin

10

Puoi facilmente usare imcache . Di seguito è riportato un codice di esempio.

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

9

Prova questo:

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

}

I problemi relativi all'affidamento a una mappa sincronizzata sono stati già discussi in altre risposte.
sanità mentale

@sergeyB: stavo cercando una soluzione simile che fosse semplice per implementare la cache ... Grazie
Prakruti Pathik

1
public static SimpleCacheManager getInstance() {dovrebbe essere public synchronized static SimpleCacheManager getInstance() {altrimenti if (instance == null) {non è thread-safe. In tal caso è possibile rimuovere l'oggetto monitor tutti insieme poiché la sincronizzazione avviene per tutte le chiamate getInstance (), vedere: javaworld.com/article/2073352/core-java/…
Can Kavaklıoğlu

Posso consigliare di utilizzare un'enumerazione per singleton? dzone.com/articles/java-singletons-using-enum
Erk



0

Prova Ehcache ? Ti consente di collegare i tuoi algoritmi di scadenza della cache in modo da poter controllare la tua funzionalità peek.

Puoi serializzare su disco, database, su un cluster ecc ...

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.