2015-06-08 8 views
7

Unten finden Sie einen Beispielcode, der die Future-Schnittstelle für einen asynchronen Aufruf verwendet. Ich brauche etwas Aufklärung über die Methode get().Garbage Collection und asynchrone Aufrufe/Future-Objekte

Future<String> future = getAsyncString(); 
//do something ... 
String msg = ""; 
if (validation) 
    return; 
else 
    msg = future.get(); 
//do something else... 
return; 

Die Zukunft Variable wird in einem Verfahren initialisiert, so dass der Variable wird in Kürze durch die GC nach der Methode der Ausführung gelöscht werden, da es nicht mehr verwendet wird. Also, in dem Fall, dass der Code die if-Anweisung eingibt, was wird der Status der JVM sein? Wie wird die JVM das Wrapped-Ergebnis verarbeiten, falls es nicht zurückgelesen wird? Beeinflusst es den Thread Pool oder den Thread Executor?

+3

Variablen werden vom GC nicht gelöscht. Der GC bereinigt Objekte, auf die keine Variablen mehr verweisen. Beachten Sie, dass eine Variable kein Objekt ist. Eine Variable ist eine * Referenz * für ein Objekt. – Jesper

+0

Nun ja, der Code schlägt vor, dass die zukünftige Instanz nur innerhalb der Methode verwendet wird. – AntJavaDev

+0

Warum validieren Sie nach 'getAsyncString()' und nicht vorher? –

Antwort

2

Wie geht die JVM mit dem Wrapped-Ergebnis um, falls niemand es zurücklesen wird?

Wenn niemand (ich meine irgendein Programm) es lesen wird, dann wird sich GC während der Speicherbereinigung darum kümmern. Aber das bedeutet nicht, dass getAsyncString() nicht vollständig ausgeführt wird, stattdessen wird es normal beendet, wenn eine normale Methode abgeschlossen ist.

+0

Nun, das ist die Antwort, die ich bestätigen möchte, wie können wir das bestätigen? Soll ich den Speicher zur Laufzeit überprüfen? – AntJavaDev

+0

Was möchten Sie bestätigen, ist es Müll gesammelt oder die Ausführung abgeschlossen ist? –

+0

nein es wird mit Sicherheit ausgeführt werden, wie die Methode aufgerufen wird, ist die Frage, was mit dem Wrapped-Ergebnis passieren wird, falls der Code nie die future.get() erreicht? Wird es ein Speicherleck oder was auch immer verursachen? – AntJavaDev

10

Wie geht die JVM mit dem Wrapped-Ergebnis um, falls niemand es zurücklesen wird?

Vermutlich haben Sie das Objekt Future von einem Executor. Damit dieser Executor das Ergebnis in Future setzen kann, enthält er einen Verweis auf die Future. Mit anderen Worten bedeutet dies nicht, dass das Future-Objekt (das sich auf dem Heap befindet) automatisch für die Garbage Collection berechtigt ist, nur weil die lokale Referenz der Methode auf das Objekt verschwindet, wenn der Aufrufstapel geöffnet wird.

Der Async-Anruf wird nicht abgebrochen oder so. Der Executor führt den Aufruf aus, füllt das Ergebnis aus und legt seinen Verweis vermutlich auf das Objekt Future ab. Bei dieses Punkt wird das Objekt unerreichbar und für Garbage Collection geeignet.

Wenn Sie sicher sind, dass Ihr Code nicht hält einen Verweis auf das Objekt Future (dh es im // do something... Teil undicht), dann können Sie sicher sein, dass das Future Objekt ist (schließlich) von der GC gesammelt . (Der Executor hat hier keine versteckten Speicherlecks.)

[...] so wird die Variable bald vom GC gelöscht.

Um genau zu sein, wird die Variable verworfen, wenn der Aufrufstapel gebloppt wird. Dies führt schließlich dazu, dass das FutureObjekt nicht erreichbar und für Garbage Collection geeignet ist. Das Objekt wird jedoch in der Regel nicht als Müll gesammelt sofort als die Methode zurückgibt.

+0

Also schlagen Sie vor, dass nach der Ausführung der Methode, selbst wenn ich die future.get() nicht aufgerufen habe, der Verweis auf das umbrochene Ergebnis immer noch da ist, da der Thread-Executor die Variable enthält? – AntJavaDev

+0

Ja, das stimmt. – aioobe

+0

@AntJavaDev Die Methode, die die Zukunft ausführt, wird nicht unterbrochen. Es wird abgeschlossen, zu welchem ​​Zeitpunkt der Executor seine Referenz freigibt und das Future-Objekt für die Garbage Collection geeignet ist. – Sinkingpoint

0

Sie haben die Garantie, dass das Objekt nicht erkannt wird, während Sie sich in einem Bereich befinden, in dem der Verweis darauf definiert ist, oder dass irgendwo im Code auf das Objekt verwiesen wird.

Dies gilt für alle Objekte, und Future macht hier keinen Unterschied.

Sobald Ihre Methode beendet ist und ihr Aufrufstapel gelöscht ist, wird Ihr Objekt zu einem späteren Zeitpunkt in der Garbage-Collection verfügbar sein, aber sicher nicht, bevor eine Referenz auf den Aufrufstapel der Methode vorhanden ist.

1

ich denke. Geplante Zukunft wird einige interne Referenzen von Threadpool-Warteschlangen bis zum Abschluss der Aufgabe haben. So kann es nicht von GC gesammelt werden, bevor die Aufgabe abgeschlossen ist.

Möglicherweise gibt es zusätzliche Abstraktionsebene zwischen Zukunft und Executor und Zukunft kann gesammelt werden. Aber ich bin sicher, dass wenn Aufgabe gesendet wird es ausgeführt wird. Egal, war Zeiger auf Zukunft gespeichert oder nicht.