Pergunta

Eu sei que é simples de implementar, mas eu quero a reutilização algo que já existe.

Problema Quero resolver é que a configuração I carga (de XML assim que eu quero cache-los) para diferentes páginas, papéis, ... então a combinação de entradas pode crescer bastante grande (mas em 99% não). Para lidar com esse 1%, eu quero ter um número máximo de itens no cache ...

Até sei que tenho encontrado org.apache.commons.collections.map.LRUMap no Apache Commons e ele parece estar bom, mas quero verificar também outra coisa. Quaisquer recomendações?

Foi útil?

Solução

Você pode usar um LinkedHashMap (Java 1.4+):

// Create cache
final int MAX_ENTRIES = 100;
Map cache = new LinkedHashMap(MAX_ENTRIES+1, .75F, true) {
    // This method is called just after a new entry has been added
    public boolean removeEldestEntry(Map.Entry eldest) {
        return size() > MAX_ENTRIES;
    }
};

// Add to cache
Object key = "key";
cache.put(key, object);

// Get object
Object o = cache.get(key);
if (o == null && !cache.containsKey(key)) {
    // Object not in cache. If null is not a possible value in the cache,
    // the call to cache.contains(key) is not needed
}

// If the cache is to be used by multiple threads,
// the cache must be wrapped with code to synchronize the methods
cache = (Map)Collections.synchronizedMap(cache);

Outras dicas

Esta é uma questão de idade, mas para a posteridade eu queria listar ConcurrentLinkedHashMap , que é o segmento de seguros, ao contrário LRUMap . O uso é bastante fácil:

ConcurrentMap<K, V> cache = new ConcurrentLinkedHashMap.Builder<K, V>()
    .maximumWeightedCapacity(1000)
    .build();

E a documentação tem algumas boas exemplos , como forma de tornar o LRU cache de tamanho baseada em vez de número-of-itens com base.

Aqui está minha implementação que me permite manter um número ideal de elementos de memória.

A questão é que eu não preciso acompanhar o que os objetos estão sendo usados ??desde que eu estou usando uma combinação de um LinkedHashMap para o MRU objetos e uma WeakHashMap para os objetos LRU. Assim, a capacidade de cache não é menos do que o tamanho MRU mais o que o GC me permite manter. Sempre que os objetos caem fora do MRU eles vão para o LRU enquanto o GC vai tê-los.

public class Cache<K,V> {
final Map<K,V> MRUdata;
final Map<K,V> LRUdata;

public Cache(final int capacity)
{
    LRUdata = new WeakHashMap<K, V>();

    MRUdata = new LinkedHashMap<K, V>(capacity+1, 1.0f, true) {
        protected boolean removeEldestEntry(Map.Entry<K,V> entry)
        {
            if (this.size() > capacity) {
                LRUdata.put(entry.getKey(), entry.getValue());
                return true;
            }
            return false;
        };
    };
}

public synchronized V tryGet(K key)
{
    V value = MRUdata.get(key);
    if (value!=null)
        return value;
    value = LRUdata.get(key);
    if (value!=null) {
        LRUdata.remove(key);
        MRUdata.put(key, value);
    }
    return value;
}

public synchronized void set(K key, V value)
{
    LRUdata.remove(key);
    MRUdata.put(key, value);
}
}

Eu também tive mesmo problema e eu não encontrei qualquer boas bibliotecas ... assim que eu criei minha própria.

simplelrucache fornece threadsafe, muito simples cache LRU, não distribuído com apoio TTL. Ele fornece duas implementações

  • Concurrent baseado em ConcurrentLinkedHashMap
  • sincronizado baseado em LinkedHashMap

Você pode encontrá-lo aqui .

Aqui é muito simples e fácil de usar o cache LRU em Java. Embora seja curta e simples é a qualidade da produção. O código é explicada (olhar para o README.md) e tem alguns testes de unidade.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top