Como implementar um cache mais usados ​​recentemente

votos
12

Qual seria a melhor forma de implementar um cache mais usados ​​recentemente de objetos?

Aqui estão os requisitos e restrições ...

  • Os objetos são armazenados como chave / valor Objeto / pares de objeto, de modo a interface seria um pouco como Hashtable get / put
  • Uma chamada para 'obter' marcaria esse objeto como o usado mais recentemente.
  • A qualquer momento, o objeto usado menos recentemente podem ser removidos do cache.
  • Pesquisas e purgas deve ser rápido (como no rápido Hashtable)
  • O número de objetos pode ser grande, então lista as pesquisas não são bons o suficiente.
  • A implementação deve ser feita usando JavaME, por isso há pouco espaço para o uso de código de terceiros ou biblioteca de classes puras a partir das bibliotecas Java padrão. Por esta razão eu estou olhando mais para respostas algorítmicos em vez de recomendações de soluções off-the-peg.
Publicado 24/02/2009 em 23:13
fonte usuário
Em outras línguas...                            


4 respostas

votos
21

Java Collections fornecer LinkedHashMap fora da caixa, que é bem adequado para caches de construção. Você provavelmente não tem isso em Java ME, mas você pode pegar o código fonte aqui:

http://kickjava.com/src/java/util/LinkedHashMap.java.htm

Se você não pode simplesmente copiar e colá-lo, olhando para ele deve começar implementando um para inclusão no seu aplicativo móvel. A idéia básica é apenas para incluir uma lista ligada através dos elementos do mapa. Se você manter este atualizado sempre que alguém não colocar ou obter, você pode eficientemente acompanhar ordem acesso e uso ordem.

Os documentos contêm instruções para a construção de um Cache MRU, substituindo o removeEldestEntry(Map.Entry)método. Tudo o que você realmente tem que fazer é fazer uma classe que estende LinkedHashMape substituir o método assim:

private static final int MAX_ENTRIES = 100;

protected boolean removeEldestEntry(Map.Entry eldest) {
   return size() > MAX_ENTRIES;
}

Há também um construtor que permite especificar se deseja que a classe para armazenar as coisas em ordem de inserção ou pelo uso, então você tem um pouco de flexibilidade para sua política de remoção, também:

public LinkedHashMap(int initialCapacity,
                     float loadFactor,
                     boolean accessOrder)

Passe verdade para uso ordem e falsa para a ordem de inserção.

Respondeu 24/02/2009 em 23:31
fonte usuário

votos
7

Um ConcurrentLinkedHashMap é difícil de construir, devido aos requisitos de bloqueio. A LinkedHashMap com um bloqueio é simples, mas nem sempre alto desempenho. Uma versão concorrente iria tentar reduzir a quantidade de bloqueio, quer por divisão de bloqueio ou, idealmente, tornando as operações CAS para fazer bloqueio muito barato. Se as operações CAS nunca se tornam caros, em seguida, semelhante divisão balde pode ser útil. Como um LRU requer escreve para cada operação de acesso, e usa uma lista duplamente ligada, isso é muito difícil de implementar com operações CAS puros. Eu tenho tentado, mas eu preciso para continuar a amadurecer meu algoritmo. Se você procurar ConcurrentLinkedHashMap, você vai ver a minha página do projeto ...

Se o Java ME não suporta operações CAS, o que eu esperaria para ser verdade, então sincronização básica é tudo que você pode fazer. Este é provavelmente bom o suficiente com um LHM, uma vez que eu só vi problemas de desempenho na contagem elevada no lado do servidor. Então uma das respostas acima.

Respondeu 25/02/2009 em 02:10
fonte usuário

votos
2

Por que implementar algo já implementado? Use Ehcache .

No entanto , se bibliotecas de terceiros são totalmente fora de questão, eu acho que você está olhando para implementar uma estrutura de dados que é algo como isto:

  • Basicamente é um HashMap (estende-se HashMap<Object, Object>se preferir)
  • Cada valor nos pontos de mapa para um objeto em uma lista ordenada, com base no que é mais utilizado.
  • Objetos usados ​​recentemente são adicionados à cabeça da lista - O(1)
  • Purga meios menos recentemente usado truncar o final da lista - O(1)
  • Ainda lhe dá Mapa pesquisas, mas ainda mantém os itens usados ​​recentemente em primeiro lugar ...
Respondeu 24/02/2009 em 23:19
fonte usuário

votos
0

Outra abordagem pode ser para dar uma olhada na seção 5.6 no Java Concurrency in Practice por Brian Goetz: "Construindo um cache de resultado eficiente, escalável". Dê uma olhada no Memoizer, embora você pode ter que personalizá-lo para seus propósitos.

Como um aparte, o que eu não consigo entender é por que Java não tem uma ConcurrentLinkedHashMap fora da caixa. Esta estrutura de dados seria muito útil para a construção de um cache.

Respondeu 24/02/2009 em 23:58
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more