web-dev-qa-db-fra.com

Quand utiliseriez-vous un WeakHashMap ou un WeakReference?

L'utilisation de références faibles est quelque chose dont je n'ai jamais vu la mise en œuvre. J'essaie donc de comprendre quel est le cas d'utilisation et comment fonctionnerait la mise en œuvre. Quand avez-vous eu besoin d'utiliser WeakHashMap ou WeakReference et comment a-t-il été utilisé?

161
18Rabbit

Un problème avec les références fortes est la mise en cache, en particulier avec les très grandes structures telles que les images. Supposons que vous ayez une application devant utiliser des images fournies par l'utilisateur, comme l'outil de conception de site Web sur lequel je travaille. Naturellement, vous souhaitez mettre en cache ces images, car leur chargement à partir du disque est très coûteux et vous voulez éviter la possibilité d'avoir deux copies de l'image (potentiellement gigantesque) en mémoire à la fois.

Parce qu'un cache d'image est censé nous empêcher de recharger des images lorsque nous n'en avons pas absolument besoin, vous vous rendrez vite compte que le cache doit toujours contenir une référence à une image déjà en mémoire. Avec des références fortes ordinaires, cependant, cette référence elle-même forcera l'image à rester en mémoire, ce qui vous obligera à déterminer quand l'image n'est plus nécessaire en mémoire et à la supprimer du cache afin qu'elle devienne éligible pour le garbage collection. Vous devez dupliquer le comportement du ramasse-miettes et déterminer manuellement si un objet doit être en mémoire ou non.

Comprendre les références faibles , Ethan Nicholas

96
Jacob Krall

Une différence à clarifier est la différence entre un WeakReference et un SoftReference.

Fondamentalement, un WeakReference sera GC-d par la JVM avec impatience, une fois que l'objet référencé ne comportera plus aucune référence dure . En revanche, un objet SoftReferenced aura tendance à être laissé en place par le ramasse-miettes jusqu'à ce qu'il ait réellement besoin de récupérer de la mémoire.

Un cache dans lequel les valeurs sont contenues dans WeakReferences serait plutôt inutile (dans un WeakHashMap, ce sont les clés faiblement référencées). SoftReferences sont utiles pour encapsuler les valeurs lorsque vous souhaitez implémenter un cache qui peut augmenter et diminuer avec la mémoire disponible

52
oxbow_lakes

Une utilisation courante de WeakReferences et de WeakHashMaps est en particulier d'ajouter des propriétés à des objets. Parfois, vous souhaitez ajouter des fonctionnalités ou des données à un objet, mais la sous-classification et/ou la composition ne sont pas une option. Dans ce cas, il est évident que vous devez créer une table de hachage reliant l'objet que vous souhaitez étendre à la propriété que vous souhaitez ajouter. . ensuite, chaque fois que vous avez besoin de la propriété, vous pouvez simplement la rechercher sur la carte. Toutefois, si les objets auxquels vous ajoutez des propriétés ont tendance à être détruits et à être beaucoup créés, vous pouvez vous retrouver avec de nombreux objets anciens dans votre carte occupant beaucoup de mémoire.

Si vous utilisez plutôt WeakHashMap, les objets quitteront votre carte dès qu'ils ne seront plus utilisés par le reste de votre programme, ce qui correspond au comportement souhaité.

Je devais le faire pour ajouter des données à Java.awt.Component Pour contourner un changement dans le JRE entre 1.4.2 et 1.5, j'aurais pu le corriger en sous-classant chaque composant qui m'intéressait int (JButton, JFrame, JPanel....) mais c'était beaucoup plus facile avec beaucoup moins de code.

30
luke

Un autre cas utile pour WeakHashMap et WeakReference est un implémentation du registre d'écoute.

Lorsque vous créez quelque chose qui veut écouter certains événements, vous enregistrez généralement un écouteur, par exemple.

manager.registerListener(myListenerImpl);

Si le manager enregistre votre écouteur avec un WeakReference, cela signifie que vous n'avez pas besoin de supprimer le registre, par exemple. avec une manager.removeListener(myListenerImpl) car elle sera automatiquement supprimée une fois que votre auditeur ou votre composant détenant l'écouteur devient indisponible.

Bien sûr, vous pouvez toujours supprimer manuellement votre auditeur, mais si vous ne l'oubliez pas ou non, cela ne provoquera pas de fuite de mémoire, et cela n'empêchera pas votre auditeur d'être nettoyé.

WeakHashMap entre-t-il dans l'image?

Le registre d'écoute qui souhaite stocker les écouteurs enregistrés sous le nom WeakReferences a besoin d'une collection pour stocker ces références. Il n'y a pas de WeakHashSet implémentation dans la bibliothèque standard Java seulement un WeakHashMap, mais on peut facilement utiliser cette dernière pour "implémenter" la fonctionnalité de la première :

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

Avec ce listenerSet pour enregistrer un nouvel écouteur, il vous suffit de l'ajouter à l'ensemble. Même s'il n'est pas supprimé explicitement, si l'écouteur n'est plus référencé, il sera automatiquement supprimé par la JVM.

20
icza

Cet article de blog illustre l'utilisation des deux classes: Java: synchronisation sur un ID . L'utilisation va quelque chose comme ça:

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 fournit des objets basés sur l'id sur lesquels se synchroniser. Les exigences sont:

  • doit renvoyer une référence au même objet pour l'utilisation simultanée d'ID équivalents
  • doit renvoyer un objet différent pour différents identifiants
  • pas de mécanisme de libération (les objets ne sont pas retournés au fournisseur)
  • ne doit pas fuir (les objets non utilisés sont éligibles pour la récupération de place)

Ceci est réalisé en utilisant une carte de stockage interne de type:

WeakHashMap<Mutex, WeakReference<Mutex>>

L'objet est à la fois clé et valeur. Lorsque rien de l'extérieur de la carte ne fait référence à l'objet, vous pouvez le récupérer. Les valeurs de la carte sont stockées avec des références exactes. Par conséquent, elles doivent être entourées d'un WeakReference afin d'éviter une fuite de mémoire. Ce dernier point est couvert dans le javadoc .

4
McDowell

Si vous voulez par exemple garder une trace de tous les objets créés d'une certaine classe. Pour toujours permettre à ces objets d'être ramassés, vous gardez une liste/carte de références faibles aux objets au lieu des objets eux-mêmes.

Maintenant, si quelqu'un pouvait m'expliquer des références fantômes, je serais heureux ...

3
JesperE

Comme indiqué ci-dessus, les références faibles sont conservées tant qu'il existe une référence forte.

Un exemple d'utilisation serait d'utiliser WeakReference dans les écouteurs, de sorte que ceux-ci ne soient plus actifs une fois que la référence principale à leur objet cible aura disparu. Notez que cela ne signifie pas que le WeakReference est supprimé de la liste des écouteurs, un nettoyage est toujours nécessaire mais peut être effectué, par exemple, à des heures programmées. Cela a également pour effet d'empêcher l'objet écouté de conserver des références fortes et d'être éventuellement une source de mémoire saturée. Exemple: composants d'interface graphique Swing faisant référence à un modèle ayant un cycle de vie plus long que la fenêtre.

Tout en jouant avec les auditeurs comme décrit ci-dessus, nous avons rapidement compris que les objets étaient collectés "immédiatement" du point de vue de l'utilisateur.

3
Louis Jacomet

J'ai fait une recherche de code de Google pour "new WeakHashMap ()".

J'ai eu un tas de correspondances du projet GNU classpath et

  1. Projet Apache xbean: WeakHashMapEditor.Java
  2. Projet Apache Lucene: CachingWrapperFilter.Java
1
anjanb