Lorsqu'un objet modifie son état d'accession, une référence à l'objet peut être placée dans une file d'attente de référence. Ces files d'attente sont utilisées par le collecteur des ordures pour communiquer avec notre code sur les modifications de l'accessibilité des objets. Ces files d'attente sont le meilleur moyen de détecter les changements d'accessibilité, bien que nous puissions également détecter les modifications d'accessibilité de l'objet en vérifiant si la valeur de retour de la méthode GET est nul.
Les objets de référence peuvent être associés à des files d'attente spécifiques lors de la construction. Chaque sous-classe de référence fournit des constructeurs de la forme suivante:
. Référence de la force publique (t RÉFÉRENCE, REFERTEUEEQ): Cette méthode crée un nouvel objet de référence avec l'objet de référence donné et enregistre l'objet de référence à la file d'attente donnée. Des références faibles et des références douces sont insérées dans la file d'attente après que le collecteur des ordures détermine que leurs objets de référence entrent dans l'état d'accès spécifique qu'ils représentent, et les deux références sont effacées avant la file d'attente d'insertion. Les références virtuelles seront également insérées dans la file d'attente après que le collecteur des ordures détermine que ses objets de référence ont entré à l'état accessible virtuel, mais ils ne seront pas effacés. Une fois que l'objet de référence est inséré dans la file d'attente par le collecteur des ordures, la valeur de retour de sa méthode GET sera certainement nul, de sorte que l'objet ne peut jamais être ressuscité.
L'enregistrement d'un objet de référence dans une file d'attente de référence ne crée pas de référence entre la file d'attente et l'objet de référence. Si notre objet de référence lui-même devient inaccessible, il ne peut pas être inséré dans la file d'attente. Par conséquent, notre application doit maintenir une forte référence à tous les objets référencés.
La classe ReferenceQueue fournit trois méthodes pour supprimer les références dans une file d'attente:
La méthode de scrutin permet à un fil de demander si une référence est dans une file d'attente et effectue une action spécifique lorsque la référence existe dans la file d'attente. La méthode de suppression peut gérer des situations plus complexes (moins courantes), où un thread dédié est responsable de la suppression des références de la file d'attente et de la réalisation d'actions appropriées. Le comportement de blocage de ces méthodes est le même que le comportement de blocage défini dans l'objet.ATT. Pour une référence spécifique, nous pouvons interroger s'il est dans la file d'attente par sa méthode Isenqueued, ou le forcer dans la file d'attente en appelant sa méthode d'equare, mais généralement ce type de bouchage est effectué par le collecteur des ordures.
Les références virtuelles dans la file d'attente de référence peuvent être utilisées pour déterminer quand un objet peut être recyclé. Nous ne pouvons accéder à aucun objet via des références virtuelles, même si l'objet est accessible à d'autres égards, car la méthode GET de référence virtuelle renvoie toujours Null. En fait, l'utilisation de références virtuelles pour trouver l'objet à recycler est le moyen le plus sûr, car les références faibles et les références douces seront insérées dans la file d'attente après la fin de l'objet, tandis que les références virtuelles sont insérées dans la file d'attente après la fin de l'objet de terminaison, c'est-à-dire qu'elle est absolument sûre. Si vous le pouvez, les références virtuelles doivent toujours être utilisées, car d'autres références auront la possibilité que la finalisation des méthodes utilise des objets endapables.
Considérez un exemple d'un gestionnaire de ressources qui peut contrôler l'accès aux collections de ressources externes. Les objets peuvent demander l'accès à une ressource externe et ne pas mettre fin à l'accès avant la fin de l'opération, après quoi ils doivent retourner la ressource utilisée au gestionnaire de ressources. Si cette ressource est partagée, ses droits d'utilisation seront transmis entre plusieurs objets et peuvent même être transmis entre plusieurs threads, il est donc difficile pour nous de déterminer quel objet est le dernier utilisateur de cette ressource, et il est donc difficile de déterminer quel morceau de code sera responsable du retour de cette ressource. Pour gérer cette situation, le gestionnaire de ressources peut réaliser le recyclage automatique de cette ressource en associant une ressource à un objet spécial appelé une clé. Tant que l'objet clé est accessible, nous pensons que cette ressource est toujours utilisée; Tant que l'objet clé peut être collecté sous forme de déchets, la ressource sera automatiquement publiée. Le code suivant est une représentation abstraite des ressources ci-dessus:
Interface Resource {void Use (clé d'objet, objet… args); void release (); }Lorsqu'une ressource est obtenue, son objet clé doit être fourni au gestionnaire de ressources. Pour une instance de ressource renvoyée, cette ressource ne peut être utilisée que s'il obtient sa clé correspondante. Cela garantit qu'après le recyclage de la clé, sa ressource correspondante ne peut plus être utilisée, même si l'objet de ressource représentant cette ressource peut toujours être accessible. Notez que l'objet de ressource ne stocke pas une forte référence à l'objet clé, ce qui est important car cela empêche l'objet clé de devenir inaccessible, ce qui fait que la ressource est inébranlable. La mise en œuvre de la ressource peut être imbriquée dans le gestionnaire de ressources:
Classe statique privée ResourceIMPl implémente Resource {int keyhash; Boolean NeedsRelease = False ResourceImpl (clé d'objet) {keyHash = System.IdentityHashCode (Key); // = configurer la ressource externe NeedsRelease = true; } public void use (objet Key, objet ... args) {if (system.IdentityHashCode (key)! = keyhash) lancez new illeqalargumentException ("Mauvaise clé" //...Utilisez la ressource} public synchronisé void release () {if (NeedsRelease) {NeedsRelease = false: // = libell the Resource}}}}}}Le code de hachage de l'objet clé est stocké lorsque la ressource est créée, et chaque fois que la méthode d'utilisation est appelée, il vérifie si la même clé est fournie. L'utilisation réelle des ressources peut également nécessiter une synchronisation, mais pour la simplicité, nous les omettons ici. La méthode de libération est responsable de la libération de la ressource. Il peut être appelé directement par l'utilisateur de ressources après utilisation, ou par le gestionnaire de ressources lorsque l'objet clé n'est plus référencé. Étant donné que nous utiliserons des threads indépendants pour surveiller la file d'attente de référence, la méthode de libération doit être synchronisée et plusieurs appels doivent être autorisés.
Le gestionnaire de ressources réel a le formulaire suivant:
Classe finale publique ResourceManager {final ReferenceQueue
L'objet clé peut être n'importe quel objet, ce qui donne aux utilisateurs de ressources une grande flexibilité par rapport au gestionnaire de ressources qui affecte les objets clés. Lorsque la méthode GetResource est appelée, un nouvel objet MPL de travail de ressources sera créé et la clé fournie à la méthode sera transmise au nouvel objet ResourceImpl. Ensuite, une référence virtuelle est créée, et son objet référentiel est la clé transmise à la méthode, puis cette référence virtuelle sera insérée dans la file d'attente de référence du gestionnaire de ressources. Les objets de référence virtuels et de référence créés à la fin seront stockés dans la table de mappage. Ce tableau de mappage a deux objectifs: l'un consiste à garder tous les objets de référence virtuels accessibles, et l'autre consiste à fournir un moyen pratique de demander l'objet de ressource réel associé à chaque référence virtuelle. (Une alternative consiste à sous-classe la fantôme et à stocker l'objet de ressource dans un champ.)
Si l'objet clé devient inaccessible, le gestionnaire de ressources utilise un thread "Reaper" séparé pour traiter la ressource. La méthode d'arrêt "fermer" l'explorateur en terminant le fil de récolteuse (en réponse à une interruption), ce qui a provoqué la méthode GetResource une exception ille-llestateException. Dans cette conception simple, toutes les références qui branchent une file d'attente après la fermeture de l'explorateur ne seront pas traitées. Le fil de la récolte est le suivant:
class ReaperThread étend Thread {public void run () {// Exécuter jusqu'à interrompre while (true) {try {référence ref = queue.remove (); Ressource res = null; synchronisé (ResourceManager.This) {res = Refs.get (ref); Réf. retirer (réf); } res .release (); Ref.Clear (); } catch (InterruptedException ex) {break; // tout fait}}}}Reaperthread est une classe interne, et le thread de moissonneuse donné fonctionnera jusqu'à ce que le gestionnaire de ressources associé soit fermé. Le thread bloque sur la méthode de suppression jusqu'à ce que la référence virtuelle associée à une clé spécifique soit insérée dans la file d'attente de référence. Cette référence virtuelle peut obtenir une référence à l'objet de ressource à partir de la table de mappage, puis cette paire "clé à référence" sera supprimée de la table de mappage. Immédiatement après, sa méthode de libération est appelée sur l'objet de ressource pour libérer la ressource. enfin,
La référence virtuelle est effacée afin que la clé puisse être recyclée.
Comme alternative à l'utilisation de threads indépendants, toute opération qui appelle la méthode de scrutin de la file d'attente de référence et libère toutes les ressources dont les clés sont devenues inaccessibles peuvent être remplacées par la méthode GetResource ", et la méthode Shutdow" peut également être utilisée pour effectuer l'opération de scrutin final. La sémantique du gestionnaire de ressources dépendra du type réel du type de ressources et de l'utilisation des ressources.
Les conceptions utilisant des files d'attente de référence sont beaucoup plus fiables que les conceptions qui utilisent directement les terminaisons (en particulier les références virtuelles). Mais nous devons nous rappeler que l'heure et l'emplacement exacts de l'objet de référence inséré dans la file d'attente de référence n'est pas certain, et nous ne savons pas si toutes les références enfichables ont été insérées dans la file d'attente de référence lorsque l'application se termine. Si nous devons nous assurer que toutes les ressources peuvent être publiées avant la fin de l'application, nous devons installer le crochet d'arrêt nécessaire ou utiliser d'autres protocoles définis par l'application pour nous assurer que cela est réalisé.