Enthält das von executorService.submit (Runnable) zurückgegebene zukünftige Objekt einen Verweis auf das runnable-Objekt?

9

Nehmen wir an, wir haben den folgenden Code:

%Vor%

Meine Fragen sind:

  1. Enthält runningTasks eine Referenz auf das Objekt task ?
  2. Wie lange hält es dafür? Wird es nach Abschluss der Aufgabe immer noch gehalten?
  3. Um Speicherverluste zu vermeiden, muss ich darauf achten, die Zukunft, die der Liste hinzugefügt wurde, zu entfernen?
Daniel Rusev 11.04.2014, 13:53
quelle

2 Antworten

2

Bis zum Zeitpunkt, an dem der Executor oder das Objekt Future einen Verweis darauf enthält, ist ein Implementierungsdetail . Wenn Ihre Aufgaben daher viel Speicher belegen, sodass Sie sich Gedanken über die Speichernutzung machen müssen, sollten Sie Ihre Aufgabe vor dem Abschluss der Aufgabe explizit bereinigen.

Wenn Sie sich OpenJDK 1.6 Quelltext von ThreadPoolExecutor , Sie können sehen, dass tatsächlich das zugrunde liegende Future Objekt tatsächlich einen Verweis auf das zugrunde liegende aufrufbare Objekt auf unbestimmte Zeit behält (d Solange es eine starke Referenz auf das Future -Objekt gibt, kann das Callable nicht GCd sein. Dies gilt auch für 1,7. Ab 1.8 wird der Verweis auf annulliert. Sie können jedoch nicht steuern, auf welche Implementierung von ExecutorService Ihre Aufgabe ausgeführt wird.

Die Verwendung von WeakReference sollte in der Praxis funktionieren, da das Future und somit das Callable -Objekt GCd sein kann, sobald die Aufgabe erledigt ist und vernünftige Implementierungen von ExecutorService den Bezug verlieren sollten, wenn die Aufgabe erledigt ist. Genau genommen hängt dies jedoch immer noch von der Implementierung des ExecutorService ab. Darüber hinaus kann die Verwendung von WeakReference einen überraschend großen Overhead hinzufügen. Es ist viel besser, das Objekt, das viel Speicher beansprucht, einfach explizit zu bereinigen. Umgekehrt, wenn Sie keine großen Objekte zuweisen, würde ich mir keine Sorgen machen.

Natürlich ist diese Diskussion völlig anders als das Speicherleck, das Sie haben werden, wenn Sie weiterhin Futures zu Ihrer Liste hinzufügen, ohne sie jemals zu entfernen. Wenn Sie dies tun, würde sogar die Verwendung von WeakReference nicht helfen. Sie haben immer noch ein Speicherleck. Durchlaufen Sie dazu einfach die Liste und entfernen Sie bereits getätigte Futures, die Ihnen nichts nützen. Es ist wirklich in Ordnung, dies jedes Mal zu tun, es sei denn, Sie haben eine lächerlich große Warteschlange Größe, da dies sehr schnell ist.

    
Enno Shioji 16.07.2014 18:53
quelle
-1
  1. Hält runningTasks (Future) eine Referenz auf das Aufgabenobjekt? --- Ja
  2. Wie lange hält es dafür? Hält es es noch nach der Aufgabe ist komplett? --- Es enthält Task-Referenz, bis der Task abgeschlossen ist, nachdem es aus der Warteschlange von ThreadPoolExecutor auch in FutureTask.finishCompletion () -Methode wir Callable (Task) Verweis auf Null entfernt. FutureTask.finishCompletion () wird innerhalb von run aufgerufen und Methoden von FuturetTask abbrechen. So in Run und Abbrechen beide Fälle Zukunft hat keinen Bezug auf Aufgabe.
  3. Um zu vermeiden, dass Daten verloren gehen, muss ich darauf achten, die Zukunft zu entfernen, die der Liste hinzugefügt wurde? --- Sie sind sicher, wenn Sie Future verwenden.

Wenn Sie ScheduledFuture verwenden, können Speicherleckprobleme auftreten, da ScheduledFuture.cancel() oder Future.cancel() im Allgemeinen seine Executor nicht benachrichtigen, dass sie abgebrochen wurde, und sie in der Warteschlange verbleibt, bis ihre Ausführungszeit erreicht ist ist eingetroffen. Es ist keine große Sache für einfache Futures, aber kann ein großes Problem für ScheduledFutures sein. Es kann dort für Sekunden, Minuten, Stunden, Tage, Wochen, Jahre oder fast unbegrenzt bleiben, abhängig von den Verzögerungen, mit denen es geplant wurde.

Weitere Einzelheiten zum Beispiel der Speicherlecksituation und ihrer Lösung finden Sie in den anderen Antwort .

    
Vipin 16.07.2014 18:20
quelle