Recherche d'un cache Java en mémoire simple [fermé]

102

Je recherche un cache Java en mémoire simple qui a une bonne concurrence (donc LinkedHashMap n'est pas assez bon), et qui peut être sérialisé sur le disque périodiquement.

Une fonctionnalité dont j'ai besoin, mais qui s'est avérée difficile à trouver, est un moyen de «jeter un coup d'œil» sur un objet. J'entends par là récupérer un objet du cache sans que le cache ne retienne l'objet plus longtemps qu'il ne l'aurait autrement.

Mise à jour: Une exigence supplémentaire que j'ai négligée de mentionner est que je dois être en mesure de modifier les objets mis en cache (ils contiennent des tableaux flottants) sur place.

Quelqu'un peut-il fournir des recommandations?

santé mentale
la source
1
Je recherche quelque chose de similaire qui soit "dans le processus" et plus léger. Je veux l'utiliser pour stocker des données dans un plugin Eclipse dans le tas. Ehcache et JCS semblent trop lourds / distribués / J2EE à mon goût.
Uri
1
duplication possible de l' API Lightweight Java Object Cache
Raedwald
Je recommanderai Apache Ignite ( ignite.apache.org )
Bhagat S.
1
Que cette question soit close (6 ans après les faits) et que les gens se demandent encore aujourd'hui, montre à quel point le système de modérateur de SO échoue.
dustinevan

Réponses:

61

Depuis que cette question a été posée à l'origine, la bibliothèque Guava de Google comprend désormais un cache puissant et flexible. Je recommanderais d'utiliser ceci.

santé mentale
la source
3
Veuillez noter que Spring ne prend plus en charge le cache Guava: stackoverflow.com/questions/44175085/...
sinner
@sanity implémente-t-il Jcache?
Gaurav
Caffine est également une bibliothèque de mise en cache agréable et performante. Caffeine est une bibliothèque de mise en cache haute performance presque optimale basée sur Java 8. Caffeine fournit un cache en mémoire utilisant une API inspirée de Google Guava
Slavus
37

Ehcache est une très bonne solution pour cela et a un moyen de voir ( getQuiet () est la méthode) de sorte qu'il ne met pas à jour l'horodatage d'inactivité. En interne, Ehcache est implémenté avec un ensemble de cartes, un peu comme ConcurrentHashMap, il présente donc des avantages similaires en matière de concurrence.

Alex Miller
la source
2
Merci, une question supplémentaire: si je récupère un objet d'EHcache (par exemple, un tableau) et le modifie - l'objet sera-t-il mis à jour dans le cache? c'est à dire. EHCache conserve-t-il des références aux objets?
sanity
1
Je pense que oui, mais pour le faire en toute sécurité, vous devez bien sûr verrouiller l'objet de manière appropriée.
Alex Miller
J'adore ehcache, cependant, c'est un pot de 10 Mo. Beaucoup trop gros.
markthegrea
23

Si vous avez besoin de quelque chose de simple, cela conviendrait-il?

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

Il ne sera pas enregistré sur le disque, mais vous avez dit que vous vouliez simple ...

Liens:

(Comme Adam l'a commenté, la synchronisation d'une carte a un impact sur les performances. Ne pas dire que l'idée n'a pas de poils dessus, mais qu'elle suffirait comme solution rapide et sale.)

Evan
la source
4
Synchroniser une carte gigantesque entière est une pénalité lourde. Vous pouvez facilement stocker des types faibles dans une carte de hachage simultanée et les supprimer périodiquement.
Adam Gent
7
ConcurrentHashMap est meilleur que Collections.synchronizedMap stackoverflow.com/questions/6692008/…
Pablo Moretti
8
En termes de performances, ConcurrentHashMap fonctionne absolument mieux, mais il ne partage pas les propriétés d'un WeakHashMap en ce qui concerne l'autorisation au garbage collector de récupérer de la mémoire. Cela peut être important ou non pour vous.
Evan
4
Ensuite, utilisez ConcurrentHashMap<WeakReference<T>>. docs.oracle.com/javase/7/docs/api/java/lang/ref/…
jdmichal
19

Une autre option pour un cache java en mémoire est cache2k . Les performances en mémoire sont supérieures à EHCache et google guava, voir la page des tests de cache2k .

Le modèle d'utilisation est similaire à celui des autres caches. Voici un exemple:

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 vous avez google goyave comme dépendance, essayer le cache de goyave peut être une bonne alternative.

cruftex
la source
cruftex, si je ferme mon application, le cache détruira toutes les données enregistrées ou non?
Menai Ala Eddine - Aladdin
10

Vous pouvez facilement utiliser imcache . Un exemple de code est ci-dessous.

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

Essaye ça:

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
la source
Les problèmes liés à l'utilisation d'une carte synchronisée ont déjà été abordés dans d'autres réponses.
santé mentale
@sergeyB: Je cherchais une solution similaire qui est simple pour implémenter le cache ... Merci
Prakruti Pathik
1
public static SimpleCacheManager getInstance() {devrait être public synchronized static SimpleCacheManager getInstance() {sinon if (instance == null) {n'est pas thread-safe. Dans ce cas, vous pouvez supprimer l'objet moniteur tous ensemble puisque la synchronisation a lieu pour tous les appels getInstance (), voir: javaworld.com/article/2073352/core-java/…
Can Kavaklıoğlu
Puis-je recommander d'utiliser une énumération pour singleton? dzone.com/articles/java-singletons-using-enum
Erk
3

Que diriez-vous de ceci: https://commons.apache.org/proper/commons-jcs/ (mis à jour à la nouvelle adresse, car JCS est maintenant dans Apache Commons)

TofuBière
la source
Il semble que @sanity voulait un cache léger.
Rodolfo
0

Essayez Ehcache ? Il vous permet de brancher vos propres algorithmes d'expiration de mise en cache afin que vous puissiez contrôler vos fonctionnalités d'aperçu.

Vous pouvez sérialiser sur disque, base de données, sur un cluster, etc.

Stephen
la source