Pergunta

O uso de referências fracas é algo que eu nunca vi uma implementação assim que eu estou tentando descobrir o que o caso de uso para eles e como a implementação iria funcionar. Quando você precisou usar um WeakHashMap ou WeakReference e como foi usado?

Foi útil?

Solução

Um problema com referências fortes é cache, em particular, com muito grande Estruturas como imagens. Suponha que você tenho uma aplicação que tem que trabalhar com imagens fornecidas pelo usuário, como a web site ferramenta de design eu trabalhar. Naturalmente você deseja armazenar em cache estes imagens, porque carregá-los a partir do disco é muito caro e você quiser evitar a possibilidade de ter dois cópias do (potencialmente) gigantesco imagem na memória ao mesmo tempo.

Porque um cache de imagem é suposto nos impedir de recarregar imagens quando nós não absolutamente precisa, você vai logo perceber que o cache deve sempre conter uma referência a qualquer imagem que já está na memória. Com referências comuns fortes, porém, que se referência irá forçar o para permanecer na memória, o que requer que você determine alguma forma quando a imagem não é mais necessária em memória e removê-lo do cache, para que se torne elegível para coleta de lixo. Você é forçado a duplicar o comportamento do lixo colector e determinar manualmente se ou não um objeto deve estar em memória.

Compreendendo referências fracas , Ethan Nicholas

Outras dicas

Uma distinção a ser claro sobre a diferença entre um WeakReference e uma SoftReference.

Basicamente um WeakReference será GC-d pela JVM ansiosamente, uma vez que o objeto referenciado não tem duras referências a ele. Um objeto SoftReferenced por outro lado, tendem a ser deixados sobre pelo coletor de lixo até que ele realmente precisa de recuperar a memória.

Um esconderijo onde os valores são realizadas dentro WeakReferences seria bastante inútil (em um WeakHashMap, são as chaves que são fracamente referenciados). SoftReferences são úteis para embrulhar os valores em torno de quando você deseja implementar um cache que pode aumentar e diminuir com a memória disponível

Um uso comum de WeakReferences e WeakHashMaps em particular é para adicionar propriedades a objetos. Ocasionalmente você quiser adicionar alguma funcionalidade ou dados para um objeto, mas subclasses e / ou composição não são uma opção, nesse caso, a coisa óbvia a fazer seria a de criar um hashmap ligando o objeto que você deseja estender para o imóvel que você deseja adicionar . em seguida, sempre que você precisar a propriedade você pode simplesmente procurá-lo no mapa. No entanto, se os objetos que você está adicionando propriedades para tendem a ficar destruído e criado muito, você pode acabar com um monte de objetos antigos em seu mapa ocupando muita memória.

Se você usar um WeakHashMap em vez dos objetos vai deixar seu mapa assim que eles já não são usados ??pelo resto do seu programa, que é o comportamento desejado.

Eu tive que fazer isso para adicionar alguns dados para java.awt.Component para contornar uma mudança no JRE entre 1.4.2 e 1.5, eu poderia ter corrigido isso por subclasses cada componente I foi int interessado (JButton, JFrame, JPanel .. ..) mas esta foi muito mais fácil com muito menos código.

Outro caso útil para WeakHashMap e WeakReference é uma implementação Registro ouvinte .

Quando você cria algo que quer ouvir a determinados eventos, normalmente você registrar um ouvinte, por exemplo.

manager.registerListener(myListenerImpl);

Se as lojas manager seu ouvinte com um WeakReference, isso significa que você não precisa remover o registo por exemplo com um manager.removeListener(myListenerImpl) porque ele será automaticamente removido uma vez que seu ouvinte ou seu componente segurando o ouvinte se torna indisponível.

Claro que você ainda pode remover manualmente o seu ouvinte, e se você não ou você esquecê-lo, ele não irá causar um vazamento de memória, e ele não vai impedir que seu ouvinte ser lixo coletado.

Onde é que WeakHashMap entram em cena?

O registro do ouvinte que whishes para armazenar registrado ouvintes como WeakReferences precisa de uma coleção para armazenar essas referências. Não existe nenhuma implementação WeakHashSet na biblioteca Java padrão apenas uma WeakHashMap mas podemos facilmente usar este último para "implementar" a funcionalidade do primeiro:

Set<ListenerType> listenerSet =
    Collections.newSetFromMap(new WeakHashMap<ListenerType, Boolean>());

Com este listenerSet para registrar um novo ouvinte, você apenas tem que adicioná-lo ao conjunto, e mesmo se ele não for removido de forma explícita, se o ouvinte não é referenciado, ele será removido automaticamente pelo JVM.

Este post demonstra o uso de ambas as classes: Java: sincronização em um ID. O uso é algo como isto:

private static IdMutexProvider MUTEX_PROVIDER = new IdMutexProvider();

public void performTask(String resourceId) {
    IdMutexProvider.Mutex mutext = MUTEX_PROVIDER.getMutex(resourceId);
    synchronized (mutext) {
        // look up the resource and do something with it
    }
}

IdMutextProvider fornece objetos com base em id para sincronizar diante. Os requisitos são:

  • deve retornar uma referência ao mesmo objeto para uso concomitante de IDs equivalentes
  • deve retornar um objeto diferente para diferentes IDs
  • nenhum mecanismo de liberação (objetos não são devolvidos para o fornecedor)
  • não deve vazar (objetos não utilizados são elegíveis para coleta de lixo)

Isto é conseguido usando um mapa de armazenamento interno do tipo:

WeakHashMap<Mutex, WeakReference<Mutex>>

O objeto é tanto chave e valor. Quando nada externo para o mapa tem uma referência duro para o objeto, que pode ser lixo coletado. Os valores no mapa são armazenadas com referências rígido, para que o valor deve ser envolto em um WeakReference para evitar uma fuga de memória. Este último ponto é abordado no javadoc .

Se você, por exemplo, quer manter o controle de todos os objetos criados de uma determinada classe. Para ainda permitir que esses objetos para ser lixo coletado, você mantém uma lista / mapa de referências fracas para os objetos em vez dos próprios objetos.

Agora, se alguém poderia explicar referências fantasmas para mim, eu ficaria feliz ...

Tal como referido acima, referência fraca são realizadas durante o tempo que existe uma referência forte.

Um exemplo de uso seria usar WeakReference dentro ouvintes, para que os ouvintes não está mais ativo são uma vez a principal referência ao seu objeto de destino está desaparecido. Note que isso não significa o WeakReference é removido da lista de ouvintes, limpando ainda é necessário, mas pode ser realizada, por exemplo, em horários programados. Isto também tem o efeito de impedir o objeto ouviu de realizar referências fortes e, eventualmente, ser uma fonte de bloat memória. Exemplo:. Balanço componentes GUI refering um modelo que tem um ciclo de vida maior que a janela

Enquanto estiver jogando com os ouvintes, como descrito acima, rapidamente percebeu que objetos são recolhidos "imediatamente" do ponto de vista do usuário.

Um uso mundo real que eu tinha para WeakReferences é se você tiver um único objeto muito grande, que é raramente usado. Você não quer mantê-lo na memória quando não é necessário; mas, se outro segmento precisa o mesmo objeto, você não quer dois deles na memória também. Você pode manter uma referência fraca para o objeto em algum lugar, e referências rígidos nos métodos que o utilizam; quando os métodos tanto de acabamento, será coletado o objeto.

Eu fiz uma pesquisa Google Code para "nova WeakHashMap ()".

Eu tenho um monte de jogos a partir do projeto GNU classpath e

  1. Apache xbean Projeto: WeakHashMapEditor.java
  2. projeto Apache Lucene: CachingWrapperFilter.java

Você pode usar WeakHashMap para implementar um cache livre de recurso para a criação do objeto expansiva.

Mas note que não é desejável ter objetos mutáveis. Usei-o para os resultados da consulta de cache (que levam cerca de 400 ms para executar) a um mecanismo de texto de pesquisa, o que raramente é atualizado.

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