Wenn ein Objekt seinen Erreichbarkeitszustand ändert, kann in einer Referenzwarteschlange ein Hinweis auf das Objekt platziert werden. Diese Warteschlangen werden vom Müllkollektor verwendet, um mit unserem Code über Änderungen der Objektzuzugehörigkeit zu kommunizieren. Diese Warteschlangen sind der beste Weg, um Änderungen der Barrierefreiheit zu erkennen, obwohl wir auch Änderungen des Objekts zu Barrierefreiheit erkennen können, indem wir prüfen, ob der Rückgabewert der GET -Methode null ist.
Referenzobjekte können bei der Konstruktion bestimmte Warteschlangen zugeordnet werden. Jede Referenzunterklasse enthält Konstruktoren der folgenden Form:
.Public -Stärke -Referenz (T Referenz, Referenzqueueq): Diese Methode erstellt ein neues Referenzobjekt mit dem angegebenen Referenzobjekt und registriert das Referenzobjekt auf die angegebene Warteschlange. Schwache Referenzen und weiche Referenzen werden in die Warteschlange eingefügt, nachdem der Müllsammler festgelegt hat, dass ihre Referenzobjekte den spezifischen Erreichbarkeitszustand eingeben, den sie darstellen, und beide Referenzen vor der Einfügungswarteschlange gelöscht werden. Virtuelle Referenzen werden auch in die Warteschlange eingefügt, nachdem der Garbage Collector festgestellt hat, dass seine Referenzobjekte in den virtuellen erreichbaren Zustand eingegeben wurden, sie jedoch nicht gelöscht haben. Sobald das Referenzobjekt vom Müllsammler in die Warteschlange eingefügt wurde, ist der Rückgabewert seiner GET -Methode definitiv null, sodass das Objekt niemals wiederbelebt werden kann.
Durch die Registrierung eines Referenzobjekts in eine Referenzwarteschlange wird keine Referenz zwischen der Warteschlange und dem Referenzobjekt erstellt. Wenn unser Referenzobjekt selbst unerreichbar wird, kann es nicht in die Warteschlange eingefügt werden. Daher muss unsere Anwendung einen starken Hinweis auf alle referenzierten Objekte beibehalten.
Die Referenzqueue -Klasse enthält drei Methoden, um Referenzen in einer Warteschlange zu entfernen:
Mit der Umfrage -Methode können ein Thread abfragen, ob sich eine Referenz in einer Warteschlange befindet, und führt eine bestimmte Aktion aus, wenn die Referenz in der Warteschlange vorliegt. Die Entfernenmethode kann komplexere (weniger verbreitete) Situationen verarbeiten, in denen ein dedizierter Thread dafür verantwortlich ist, Referenzen aus der Warteschlange zu entfernen und geeignete Aktionen auszuführen. Das Blockierverhalten dieser Methoden ist das gleiche wie das im Objekt definierte Blockierungsverhalten. Für eine bestimmte Referenz können wir abfragen, ob sie sich in der Warteschlange nach seiner Isenque -Methode befindet, oder sie in die Warteschlange zwingen, indem sie seine Enqueue -Methode aufruft. In der Regel wird diese Art von Anschluss vom Müllsammler durchgeführt.
Virtuelle Referenzen in der Referenzwarteschlange können verwendet werden, um zu bestimmen, wann ein Objekt recycelt werden kann. Wir können über virtuelle Referenzen nicht auf ein Objekt zugreifen, auch wenn das Objekt auf andere Weise erreichbar ist, da die GET -Methode der virtuellen Referenz immer null zurückgibt. In der Tat ist es am sichersten, virtuelle Referenzen zu finden, um das zu recycelte Objekt zu finden, da schwache Referenzen und weiche Referenzen in die Warteschlange eingefügt werden, nachdem das Objekt beendet werden kann, während virtuelle Referenzen in die Warteschlange eingefügt werden, nachdem das Beendigung von Objekt beendet wird. Wenn Sie können, sollten immer virtuelle Referenzen verwendet werden, da andere Referenzen die Möglichkeit haben, dass die Methoden endbare Objekte verwenden.
Betrachten Sie ein Beispiel für einen Ressourcenmanager, der den Zugriff auf externe Ressourcensammlungen steuern kann. Objekte können Zugriff auf eine externe Ressource anfordern und den Zugriff erst beenden, wenn der Vorgang abgeschlossen ist. Danach sollten sie die an den Ressourcenmanager verwendete Ressource zurückgeben. Wenn diese Ressource geteilt wird, werden die Nutzungsrechte zwischen mehreren Objekten übergeben und können sogar zwischen mehreren Threads übergeben werden. Daher ist es für uns schwierig zu bestimmen, welcher Objekt der letzte Benutzer dieser Ressource ist, und es ist daher schwierig zu bestimmen, welches Code -Stück für die Rückgabe dieser Ressource verantwortlich ist. Um diese Situation zu bewältigen, kann der Ressourcenmanager automatisch Recycling dieser Ressource erreichen, indem er eine Ressource mit einem speziellen Objekt, das als Schlüssel bezeichnet wird, verbindet. Solange das Schlüsselobjekt erreichbar ist, denken wir, dass diese Ressource noch verwendet wird. Solange das Schlüsselobjekt als Müll gesammelt werden kann, wird die Ressource automatisch veröffentlicht. Der folgende Code ist eine abstrakte Darstellung der oben genannten Ressourcen:
Schnittstellenressource {void use (Objektschlüssel, Objekt… args); void release (); }Wenn eine Ressource erhalten wird, muss dem Ressourcenmanager ihr Schlüsselobjekt zur Verfügung gestellt werden. Für eine zurückgegebene Ressourceninstanz kann diese Ressource nur verwendet werden, wenn sie ihren entsprechenden Schlüssel erhält. Dies stellt sicher, dass nach dem Recycling des Schlüssels die entsprechende Ressource nicht mehr verwendet werden kann, selbst wenn das Ressourcenobjekt, das diese Ressource darstellt, möglicherweise weiterhin zugänglich ist. Beachten Sie, dass das Ressourcenobjekt keinen starken Hinweis auf das Schlüsselobjekt speichert, was wichtig ist, da dies verhindert, dass das Schlüsselobjekt unerreichbar wird, was dazu führt, dass die Ressource nicht beantragbar ist. Die Implementierung von Ressourcen kann im Ressourcenmanager verschachtelt werden:
private statische Klasse ResourceImpl implementiert Ressource {int keyhash; boolean bedarfsRelease = false ResourceImpl (Objektschlüssel) {KeyHash = System.IdentityHashCode (Schlüssel); // = Einrichten Sie die externe Ressource Bedürfnisse bedarfsRelease = true; } public void use (Objektschlüssel, Objekt ... args) {if (System.IdentityHashCode (Schlüssel)!Der Hash -Code des Schlüsselobjekts wird gespeichert, wenn die Ressource erstellt wird, und wenn die Verwendung der Verwendungsmethode aufgerufen wird, wird überprüft, ob derselbe Schlüssel bereitgestellt wird. Die tatsächliche Verwendung von Ressourcen kann auch eine Synchronisation erfordern, aber zum Einfachheit halber lassen wir sie hier weg. Die Freigabemethode ist für die Veröffentlichung der Ressource verantwortlich. Es kann direkt vom Ressourcenbenutzer nach der Verwendung oder vom Ressourcenmanager aufgerufen werden, wenn das Schlüsselobjekt nicht mehr verwiesen wird. Da wir unabhängige Threads verwenden, um die Referenzwarteschlange zu überwachen, muss die Freigabemethode synchronisiert und mehrere Aufrufe zulässig sein.
Der tatsächliche Ressourcenmanager hat das folgende Formular:
öffentliche endgültige Klasse ResourceManager {endgültige Referenzqueue
Das Schlüsselobjekt kann jedes Objekt sein, das Ressourcennutzern eine große Flexibilität bietet, im Vergleich dazu, dass der Ressourcenmanager Schlüsselobjekte zuweist. Wenn die GetResource -Methode aufgerufen wird, wird ein neues Ressourcenarbeitsobjekt erstellt, und der Schlüssel, der der Methode bereitgestellt wird, wird an das neue Ressourcen -Objekt übergeben. Anschließend wird eine virtuelle Referenz erstellt, und sein Referenzobjekt ist der Schlüssel, der an die Methode übergeben wird, und dann wird diese virtuelle Referenz in die Referenzwarteschlange des Ressourcenmanagers eingefügt. Die am Ende erstellten virtuellen Referenz- und Referenzobjekte werden in der Mapping -Tabelle gespeichert. Diese Zuordnungstabelle hat zwei Zwecke: Eine besteht darin, alle virtuellen Referenzobjekte erreichbar zu halten, und der andere ist es, eine bequeme Möglichkeit zu bieten, das tatsächliche Ressourcenobjekt abzufragen, das jeder virtuellen Referenz zugeordnet ist. (Eine Alternative besteht darin, Phantomreferenz zu unterklassen und das Ressourcenobjekt in einem Feld zu speichern.)
Wenn das Schlüsselobjekt nicht erreichbar wird, verwendet der Ressourcenmanager einen separaten "Reaper" -Thread, um die Ressource zu verarbeiten. Die Shutdown-Methode "schließen" den Explorer, indem Sie den Harvester-Thread beenden (als Reaktion auf einen Interrupt), wodurch die GetResource-Methode eine Ausnahme von Ille-LlllestateException ausgelöst hat. In diesem einfachen Design werden alle Referenzen, die eine Warteschlange nach der Schließung des Explorers anschließen, nicht verarbeitet. Der tatsächliche Harvester -Faden lautet wie folgt:
Klasse ReaperThread erweitert Thread {public void run () {// rennen bis unterbrochen (true) {try {reference ref = queue.remove (); Ressource res = null; synchronized (ResourceManager.This) {res = refs.get (ref); Refs. entfernen (ref); } res .release (); Ref.Clear (); } catch (InterruptedException ex) {break; // alle erledigt}}}}ReaperThread ist eine interne Klasse, und der angegebene Harvester -Thread wird ausgeführt, bis der damit verbundene Ressourcenmanager geschlossen ist. Die Fadenblöcke der Methode entfernen, bis die virtuelle Referenz, die einem bestimmten Schlüssel zugeordnet ist, in die Referenzwarteschlange eingefügt wird. Diese virtuelle Referenz kann einen Verweis auf das Ressourcenobjekt aus der Zuordnungstabelle erhalten. Anschließend wird dieses "Schlüssel zu Referenz" aus der Zuordnungstabelle entfernt. Unmittelbar danach wird seine Freigabemethode auf das Ressourcenobjekt aufgerufen, um die Ressource freizugeben. endlich,
Die virtuelle Referenz wird so gelöscht, dass der Schlüssel recycelt werden kann.
Als Alternative zur Verwendung unabhängiger Threads kann jeder Vorgang, der die Umfragemethode in der Referenzwarteschlange aufruft, und alle Ressourcen freigibt, deren Schlüssel nicht erreichbar geworden ist, kann durch die GetResource -Methode "Methode" ersetzt werden, und die Shutdow -Methode kann auch zur Durchführung des endgültigen Umfragevorgangs verwendet werden. Die Semantik des Ressourcenmanagers hängt vom tatsächlichen Ressourcentyp und dem Ressourcennutzungsmuster ab.
Entwürfe mit Referenzwarteschlangen sind viel zuverlässiger als Designs, die Terminationen direkt verwenden (insbesondere virtuelle Referenzen). Wir müssen uns jedoch daran erinnern, dass die genaue Zeit und der genaue Ort des in die Referenzwarteschlange eingefügten Referenzobjekts nicht sicher sind, und wir sind uns auch nicht sicher, ob alle steckbaren Referenzen in die Referenzwarteschlange eingefügt wurden, wenn die Anwendung endet. Wenn wir sicherstellen müssen, dass alle Ressourcen vor dem Ende des Anwendungsabschlusses veröffentlicht werden können, müssen wir den erforderlichen Stilldown -Hook installieren oder andere von der Anwendung definierte Protokolle verwenden, um sicherzustellen, dass dies erreicht wird.