Question

L’utilisation de références faibles est quelque chose dont je n’ai jamais vu l’implémentation. J’essaie donc de comprendre quel est leur cas d’utilisation et comment l’application fonctionnerait. Quand avez-vous eu besoin d'utiliser un WeakHashMap ou un WeakReference et comment a-t-il été utilisé?

Était-ce utile?

La solution

  

Un problème avec les références fortes est   mise en cache, notamment avec de très grandes   des structures comme des images. Supposons que vous   avoir une application qui doit fonctionner   avec des images fournies par l'utilisateur, comme le   outil de conception de sites Web sur lequel je travaille.   Naturellement, vous voulez mettre en cache ces   images, parce que les charger depuis le disque   est très cher et vous voulez   éviter la possibilité d'avoir deux   des copies du (potentiellement gigantesque)   image en mémoire à la fois.

     

Parce qu'un cache d'image est supposé   nous empêcher de recharger des images lorsque   nous n'avons pas absolument besoin de, vous allez   se rendre rapidement compte que le cache devrait   toujours contenir une référence à   image qui est déjà en mémoire. Avec   références fortes ordinaires, cependant,   cette référence elle-même forcera la   l'image pour rester en mémoire, ce qui   vous oblige à déterminer en quelque sorte quand   l'image n'est plus nécessaire dans   mémoire et retirez-le du cache,   de sorte qu'il devient admissible à   collecte des ordures. Vous êtes obligé de   dupliquer le comportement de la poubelle   collecteur et déterminer manuellement   si un objet doit ou non être dans   mémoire.

Comprendre les références faibles , Ethan Nicholas

Autres conseils

La différence entre un WeakReference et un SoftReference est claire.

Fondamentalement, une WeakReference sera GC-d par la machine virtuelle Java avec impatience, une fois que l'objet référencé ne comporte plus de référence hard . En revanche, un objet SoftReference d aura tendance à être laissé en suspens jusqu'à ce qu'il ait réellement besoin de récupérer de la mémoire.

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

Une utilisation courante de WeakReference et de WeakHashMap est notamment utilisée pour 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 tendent à être détruits et à être beaucoup créés, vous pouvez vous retrouver avec de nombreux objets anciens sur votre carte occupant beaucoup de mémoire.

Si vous utilisez un 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 faire cela 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 I était intéressé int ( JButton , JFrame , JPanel ....), mais c'était beaucoup plus facile avec beaucoup moins de code.

Un autre cas utile pour WeakHashMap et WeakReference est une implémentation de registre d'écouteur .

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 un manager.removeListener (myListenerImpl) car il sera automatiquement supprimé une fois que votre écouteur 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 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 la forme WeakReference a besoin d'une collection pour stocker ces références. Il n'y a pas d'implémentation WeakHashSet dans la bibliothèque Java standard, mais seulement un WeakHashMap , mais nous pouvons facilement utiliser cette dernière pour " implémenter " la fonctionnalité du premier:

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

Avec ce listenerSet pour enregistrer un nouvel auditeur, il vous suffit de l'ajouter à cet 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 machine virtuelle Java.

Cet article de blog illustre l'utilisation des deux classes: Java: synchronisation sur un identifiant . L'usage ressemble à ceci:

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 un id sur lesquels se synchroniser. Les exigences sont les suivantes:

  • 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 renvoyé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 placées dans un WeakReference pour éviter toute fuite de mémoire. Ce dernier point est traité dans le javadoc . .

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

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

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.

L’utilisation réelle de WeakReferences dans le monde réel est si vous avez un seul objet très volumineux qui est rarement utilisé. Vous ne voulez pas le garder en mémoire quand ce n'est pas nécessaire; mais si un autre thread a besoin du même objet, vous ne voulez pas non plus en garder deux en mémoire. Vous pouvez conserver une référence faible à l'objet quelque part et des références directes dans les méthodes qui l'utilisent. lorsque les deux méthodes finissent, l'objet sera collecté.

J'ai effectué une recherche de code dans 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

vous pouvez utiliser faibleshashmap pour implémenter une mise en cache sans ressource pour la création d’objets expansifs.

mais notez qu'il n'est pas souhaitable d'avoir des objets mutables. Je l'ai utilisé pour mettre en cache les résultats de la requête (dont l'exécution prend environ 400 ms) dans un moteur de recherche de texte, qui est rarement mis à jour.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top