O uso de referências fracas é algo que eu nunca vi uma implementação, então estou tentando descobrir qual é o caso de uso para eles e como a implementação funcionaria. Quando você precisou usar um WeakHashMap
ou WeakReference
e como foi usado?
O uso de referências fracas é algo que eu nunca vi uma implementação, então estou tentando descobrir qual é o caso de uso para eles e como a implementação funcionaria. Quando você precisou usar um WeakHashMap
ou WeakReference
e como foi usado?
Respostas:
Um problema com referências fortes é o armazenamento em cache, principalmente com estruturas muito grandes, como imagens. Suponha que você tenha um aplicativo que funcione com imagens fornecidas pelo usuário, como a ferramenta de design de sites na qual trabalho. Naturalmente, você deseja armazenar em cache essas imagens, porque carregá-las em disco é muito caro e evita a possibilidade de ter duas cópias da imagem (potencialmente gigantesca) na memória de uma só vez.
Como um cache de imagem deve impedir a recarga de imagens quando não é absolutamente necessário, você perceberá rapidamente que o cache deve sempre conter uma referência a qualquer imagem que já esteja na memória. No entanto, com referências fortes comuns, essa referência forçará a imagem a permanecer na memória, o que exige que você determine de alguma forma quando a imagem não é mais necessária na memória e remova-a do cache, para que se torne elegível para a coleta de lixo. Você é forçado a duplicar o comportamento do coletor de lixo e determinar manualmente se um objeto deve ou não estar na memória.
Noções básicas sobre referências fracas , Ethan Nicholas
WeakHashMap
.
WeakReference
versus SoftReference
Uma distinção a ser esclarecida é a diferença entre a WeakReference
e a SoftReference
.
Basicamente, um WeakReference
será GC-d pela JVM ansiosamente, uma vez que o objecto não tem referenciado rígidos referências a ele. Um SoftReference
objeto d, por outro lado, tenderá a ser deixado pelo coletor de lixo até que ele realmente precise recuperar a memória.
Um cache em que os valores são mantidos dentro de WeakReference
s seria bastante inútil (em a WeakHashMap
, são as chaves que são pouco referenciadas). SoftReferences
são úteis para agrupar os valores quando você deseja implementar um cache que pode aumentar e diminuir com a memória disponível.
Um uso comum de WeakReference
s e WeakHashMap
s, em particular, é para adicionar propriedades a objetos. Ocasionalmente, você deseja adicionar alguma funcionalidade ou dados a um objeto, mas a subclasse e / ou composição não são uma opção. Nesse caso, a coisa mais óbvia a ser feita é criar um mapa de hash vinculando o objeto que você deseja estender à propriedade que deseja adicionar. . sempre que precisar da propriedade, basta procurar no mapa. No entanto, se os objetos aos quais você está adicionando propriedades tendem a ser destruídos e criados muito, você pode acabar com muitos objetos antigos em seu mapa, ocupando bastante memória.
Se você usar um, WeakHashMap
os objetos sairão do seu mapa assim que não forem mais usados pelo resto do seu programa, que é o comportamento desejado.
Eu tive que fazer isso para adicionar alguns dados para java.awt.Component
obter em torno de 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 de registro de ouvinte .
Quando você cria algo que deseja ouvir determinados eventos, geralmente registra um ouvinte, por exemplo
manager.registerListener(myListenerImpl);
Se você manager
armazena seu ouvinte com a WeakReference
, isso significa que você não precisa remover o registro, por exemplo, com a manager.removeListener(myListenerImpl)
porque ele será removido automaticamente assim que seu ouvinte ou seu componente que estiver segurando o ouvinte ficar indisponível.
É claro que você ainda pode remover manualmente o ouvinte, mas se você não o esquecer ou esquecer, isso não causará vazamento de memória e não impedirá que o ouvinte seja coletado de lixo.
Onde WeakHashMap
entra em cena?
O registro do ouvinte que deseja armazenar ouvintes registrados como WeakReference
s precisa de uma coleção para armazenar essas referências. Não há WeakHashSet
implementação na biblioteca Java padrão apenas a, WeakHashMap
mas podemos facilmente usar a última para "implementar" a funcionalidade da primeira:
Set<ListenerType> listenerSet =
Collections.newSetFromMap(new WeakHashMap<ListenerType, Boolean>());
Com isso listenerSet
para registrar um novo ouvinte, basta adicioná-lo ao conjunto e, mesmo que não seja removido explicitamente, se o ouvinte não for mais referenciado, ele será removido automaticamente pela JVM.
WeakHashMap
é quando você precisa HashMap
de alguns objetos. Então wow você não tem que fazer manualmente hashmap.remove nunca porque os itens são automagicamente removido uma vez que o obj está fora do escopo! Literalmente mágica! Um truque mágico tão feio é um facepalm completo .
WeakReference
simplifica bastante a base de código e evita erros desnecessários relacionados à falha no cancelamento da assinatura. Que desvantagem?
Esta postagem no blog demonstra o uso de ambas as classes: Java: sincronizando em um ID . O uso é mais ou menos assim:
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 baseados em identificação para sincronização. Os requisitos são:
Isso é obtido usando um mapa de armazenamento interno do tipo:
WeakHashMap<Mutex, WeakReference<Mutex>>
O objeto é chave e valor. Quando nada externo ao mapa tem uma referência concreta ao objeto, ele pode ser coletado como lixo. Os valores no mapa são armazenados com referências concretas , portanto, o valor deve ser agrupado em um WeakReference para evitar um vazamento de memória. Este último ponto é coberto no javadoc .
Se você, por exemplo, deseja acompanhar todos os objetos criados para uma determinada classe. Para ainda permitir a coleta de lixo desses objetos, mantenha uma lista / mapa de referências fracas aos objetos, em vez dos objetos em si.
Agora, se alguém pudesse me explicar referências fantasmas, eu ficaria feliz ...
Como mencionado acima, a referência fraca é mantida enquanto existir uma referência forte.
Um exemplo de uso seria usar WeakReference dentro dos ouvintes, para que os ouvintes não fiquem mais ativos depois que a referência principal ao objeto de destino se for. Observe que isso não significa que o WeakReference é removido da lista de ouvintes, a limpeza ainda é necessária, mas pode ser executada, por exemplo, em horários programados. Isso também tem o efeito de impedir que o objeto escutado mantenha fortes referências e, eventualmente, seja uma fonte de inchaço da memória. Exemplo: componentes da GUI Swing que referenciam um modelo com um ciclo de vida mais longo que a janela.
Ao brincar com os ouvintes, conforme descrito acima, rapidamente percebemos que os objetos são coletados "imediatamente" do ponto de vista do usuário.
Um uso do mundo real que eu tive para o WeakReferences é se você tiver um único objeto muito grande que raramente é usado. Você não deseja mantê-lo na memória quando não for necessário; mas, se outro encadeamento precisar do mesmo objeto, você também não deseja dois na memória. Você pode manter uma referência fraca ao objeto em algum lugar e referências concretas nos métodos que o usam; quando os métodos terminarem, o objeto será coletado.
Eu fiz uma pesquisa de código do google por "new WeakHashMap ()".
Eu recebi várias correspondências do projeto do caminho de classe GNU e
você pode usar ohashashmap para implementar um cache sem recursos para criação de objetos expansiva.
mas observe que não é desejável ter objetos mutáveis. usei-o para armazenar em cache os resultados da consulta (que levam cerca de 400 ms para executar) em um mecanismo de pesquisa de texto, que raramente é atualizado.