Procurando por cache simples em memória Java [fechado]

102

Estou procurando um cache em memória Java simples que tenha boa simultaneidade (portanto, LinkedHashMap não é bom o suficiente) e que pode ser serializado em disco periodicamente.

Um recurso de que preciso, mas que se mostrou difícil de encontrar, é uma maneira de "espiar" um objeto. Com isso, quero dizer recuperar um objeto do cache sem fazer com que o cache segure o objeto por mais tempo do que o faria de outra forma.

Atualização: um requisito adicional que esqueci de mencionar é que preciso ser capaz de modificar os objetos em cache (eles contêm matrizes flutuantes) no local.

Alguém pode fornecer alguma recomendação?

sanidade
fonte
1
Estou procurando algo semelhante que esteja "dentro do processo" e mais leve. Eu quero usá-lo para armazenar alguns dados dentro de um plugin Eclipse no heap. Ehcache e JCS parecem muito pesados ​​/ distribuídos / J2EE para o meu gosto.
Uri
1
possível duplicata da API de cache Lightweight Java Object
Raedwald
Vou recomendar o Apache Ignite ( ignite.apache.org )
Bhagat S.
1
Que esta questão foi encerrada (6 anos após o fato) e ainda é algo que as pessoas estão se perguntando hoje, mostra como o sistema de moderador do SO está falhando.
dustinevan

Respostas:

61

Como essa pergunta foi feita originalmente, a biblioteca Guava do Google agora inclui um cache poderoso e flexível. Eu recomendaria usar isso.

sanidade
fonte
3
Observe que o Spring não oferece mais suporte ao cache de Guava: stackoverflow.com/questions/44175085/…
sinner
@sanity ele implementa Jcache?
gaurav
Caffine também é uma biblioteca de cache agradável e de alto desempenho. Caffeine é uma biblioteca de cache de alto desempenho quase ideal baseada em Java 8. O Caffeine fornece um cache na memória usando uma API inspirada no Google Guava
Slavus,
37

Ehcache é uma solução muito boa para isso e tem uma maneira de espiar ( getQuiet () é o método) de forma que não atualize o timestamp ocioso. Internamente, o Ehcache é implementado com um conjunto de mapas, como o ConcurrentHashMap, portanto, tem tipos semelhantes de benefícios de simultaneidade.

Alex Miller
fonte
2
Obrigado, uma pergunta adicional: se eu recuperar um objeto do EHcache (digamos, uma matriz) e modificá-lo - o objeto será atualizado no cache? ie. O EHCache está mantendo referências aos objetos?
sanidade
1
Acredito que sim, mas para fazer isso com segurança você deve travar o objeto de forma adequada, é claro.
Alex Miller
Eu amo ehcache, porém, é um frasco de 10 MB. Grande demais.
markthegrea
23

Se você está precisando de algo simples, isso seria adequado?

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

Não vai salvar no disco, mas você disse que queria simples ...

Links:

(Como Adam comentou, sincronizar um mapa tem um impacto no desempenho. Não estou dizendo que a ideia não tem cabelos, mas seria suficiente como uma solução rápida e suja.)

Evan
fonte
4
Sincronizar um mapa gigantesco inteiro é uma penalidade pesada. Você pode facilmente armazenar tipos fracos em um mapa hash simultâneo e removê-los periodicamente.
Adam Gent
7
ConcurrentHashMap é melhor do que Collections.synchronizedMap stackoverflow.com/questions/6692008/…
Pablo Moretti
8
Em termos de desempenho, ConcurrentHashMap tem um desempenho absolutamente melhor, mas não compartilha as propriedades de um WeakHashMap no que diz respeito a permitir que o coletor de lixo recupere memória. Isso pode ou não ser importante para você.
Evan
4
Então use ConcurrentHashMap<WeakReference<T>>. docs.oracle.com/javase/7/docs/api/java/lang/ref/…
jdmichal
19

Outra opção para um cache java em memória é cache2k . O desempenho na memória é superior ao EHCache e google guava, consulte a página de benchmarks cache2k .

O padrão de uso é semelhante a outros caches. Aqui está um exemplo:

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 você tiver o google goiaba como dependência, experimentar o cache de goiaba pode ser uma boa alternativa.

cruftex
fonte
cruftex, se eu fechar meu aplicativo o cache vai destruir todos os dados cadastrados ou não?
Menai Ala Eddine - Aladdin
10

Você pode usar o imcache facilmente . Um exemplo de código está abaixo.

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

Experimente isto:

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
fonte
Os problemas em confiar em um mapa sincronizado já foram discutidos em outras respostas.
sanidade
@sergeyB: Eu estava procurando uma solução semelhante que seja simples para implementar o cache ... Obrigado
Prakruti Pathik
1
public static SimpleCacheManager getInstance() {deve ser public synchronized static SimpleCacheManager getInstance() {caso contrário, if (instance == null) {não é thread-safe. Nesse caso, você pode remover o objeto do monitor todos juntos, pois a sincronização ocorre para todas as chamadas getInstance (), consulte: javaworld.com/article/2073352/core-java/…
Can Kavaklıoğlu
Posso recomendar o uso de um enum para singleton? dzone.com/articles/java-singletons-using-enum
Erk
0

Experimente Ehcache ? Ele permite que você conecte seus próprios algoritmos de expiração de cache para que você possa controlar sua funcionalidade de visualização.

Você pode serializar em disco, banco de dados, em um cluster, etc ...

Stephen
fonte