Ich habe in den letzten paar Stunden ziemlich viel darüber gelesen, und ich kann einfach keinen Grund ( gültigen Grund) erkennen, shutdown()
auf den ExecutorService
zuzugreifen, es sei denn, wir haben eine riesige Anwendung, die Dutzende und Dutzende verschiedener Executor-Dienste speichert, für die sie nicht verwendet werden eine lange Zeit.
Das einzige, was das Herunterfahren bewirkt (soweit ich weiß), ist das, was ein normaler Thread tut, sobald es fertig ist. Wenn der normale Thread die Ausführungsmethode von Runnable (oder Callable) beendet, wird sie zur Erfassung an Garbage Collection übergeben. Mit Executor Service werden die Threads einfach angehalten und nicht für die Garbage Collection angekreuzt. Dafür wird das Herunterfahren benötigt.
Ok zurück zu meiner Frage. Gibt es einen Grund, Shutdown ExecutorService
sehr oft oder sogar direkt nach dem Absenden einiger Aufgaben aufzurufen ? Ich möchte den Fall hinter mir lassen, dass jemand es tut und gleich danach anruft, awaitTermination()
da dies bestätigt wird. Sobald wir das tun, müssen wir noch einmal ein neues erstellen ExecutorService
, um dasselbe zu tun. Ist das nicht die ganze Idee für die ExecutorService
, die Threads wiederzuverwenden? Warum also das ExecutorService
so schnell zerstören ?
Ist es nicht eine rationale Methode, einfach zu erstellen ExecutorService
(oder zu koppeln, je nachdem, wie viele Sie benötigen), dann während der Ausführung der Anwendung die Aufgaben an sie weiterzugeben, sobald sie ausgeführt werden, und dann beim Beenden der Anwendung oder in einigen anderen wichtigen Phasen diese Ausführenden herunterzufahren ?
Ich möchte eine Antwort von einigen erfahrenen Programmierern erhalten, die mit ExecutorServices viel asynchronen Code schreiben.
Zweite Nebenfrage, etwas kleiner befasst sich mit Android-Plattform. WENN einige von Ihnen sagen, dass es nicht die beste Idee ist, Executoren jedes Mal herunterzufahren und auf Android zu programmieren, können Sie mir sagen, wie Sie mit diesen Shutdowns umgehen (um genau zu sein - wenn Sie sie ausführen), wenn wir mit verschiedenen Ereignissen von Anwendungslebenszyklus.
Aufgrund des CommonsWare-Kommentars habe ich den Beitrag neutral gemacht. Ich bin wirklich nicht daran interessiert, darüber zu Tode zu streiten, und es scheint, dass es dorthin führt. Ich bin nur daran interessiert zu erfahren, was ich hier von erfahrenen Entwicklern gefragt habe, wenn sie bereit sind, ihre Erfahrungen zu teilen. Vielen Dank.
quelle
Antworten:
Die
shutdown()
Methode bewirkt eines: Verhindert, dass Clients mehr Arbeit an den Executor-Service senden. Dies bedeutet, dass alle vorhandenen Aufgaben weiterhin vollständig ausgeführt werden, sofern keine anderen Maßnahmen ergriffen werden. Dies gilt auch für geplante Aufgaben, z. B. für einen ScheduledExecutorService: Neue Instanzen der geplanten Aufgabe werden nicht ausgeführt. Dies kann in verschiedenen Szenarien hilfreich sein.Angenommen, Sie haben eine Konsolenanwendung, auf der ein Executor-Dienst N Aufgaben ausführt. Wenn der Benutzer STRG-C drückt, wird die Anwendung möglicherweise ordnungsgemäß beendet. Was bedeutet es anmutig? Möglicherweise möchten Sie, dass Ihre Anwendung nicht mehr Aufgaben an den Executor-Service senden kann, und gleichzeitig möchten Sie warten, bis Ihre vorhandenen N Aufgaben abgeschlossen sind. Sie können dies als letzten Ausweg mit einem Abschalthaken erreichen:
final ExecutorService service = ... // get it somewhere Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { @Override public void run() { System.out.println("Performing some shutdown cleanup..."); service.shutdown(); while (true) { try { System.out.println("Waiting for the service to terminate..."); if (service.awaitTermination(5, TimeUnit.SECONDS)) { break; } } catch (InterruptedException e) { } } System.out.println("Done cleaning"); } }));
Dieser Hook beendet den Dienst, wodurch verhindert wird, dass Ihre Anwendung neue Aufgaben sendet, und wartet, bis alle vorhandenen Aufgaben abgeschlossen sind, bevor die JVM heruntergefahren wird. Die Wartezeit wird für 5 Sekunden blockiert und gibt true zurück, wenn der Dienst heruntergefahren wird. Dies erfolgt in einer Schleife, damit Sie sicher sind, dass der Dienst irgendwann heruntergefahren wird. Die InterruptedException wird jedes Mal verschluckt. Dies ist der beste Weg, um einen Executor-Dienst herunterzufahren, der in Ihrer gesamten Anwendung wiederverwendet wird.
Dieser Code ist nicht perfekt. Wenn Sie nicht absolut sicher sind, dass Ihre Aufgaben irgendwann beendet werden, möchten Sie möglicherweise auf eine bestimmte Zeitüberschreitung warten und dann einfach beenden und die laufenden Threads verlassen. In diesem Fall ist es sinnvoll, auch
shutdownNow()
nach dem Timeout aufzurufen, um die laufenden Threads zu unterbrechen (shutdownNow()
Sie erhalten auch eine Liste der Aufgaben, die auf die Ausführung warten). Wenn Ihre Aufgaben auf Unterbrechungen reagieren sollen, funktioniert dies einwandfrei.Ein weiteres interessantes Szenario ist, wenn Sie einen ScheduledExecutorService haben, der eine periodische Aufgabe ausführt. Die einzige Möglichkeit, die Kette periodischer Aufgaben zu stoppen, ist ein Anruf
shutdown()
.EDIT: Ich möchte hinzufügen, dass ich nicht empfehlen würde, einen Shutdown-Hook zu verwenden, wie oben im allgemeinen Fall gezeigt: Er kann fehleranfällig sein und sollte nur ein letzter Ausweg sein. Wenn Sie viele Shutdown-Hooks registriert haben, ist die Reihenfolge, in der sie ausgeführt werden, undefiniert, was möglicherweise unerwünscht ist. Ich würde eher die Anwendung explizit rufen
shutdown()
aufInterruptedException
.quelle
shutdown()
ihn niemals auf, damit Sie keine Ressourcen verschwenden, wenn dies nicht erforderlich ist. Wenn die Anwendung heruntergefahren wird, werden die Threads im Pool möglicherweise durch Müll gesammelt (nachdem sie standardmäßig 60 Sekunden lang inaktiv waren). Beachten Sie, dass SieThreadPoolExecutor
direkt einen Pool erstellen können, wenn Sie möchten, dass der Pool begrenzt wird oder eine andere Thread-Lebensdauer haben soll .Ja. Sie sollten nicht häufig zerstören und neu erstellen
ExecutorService
. InitialisierenExecutorService
Sie bei Bedarf (meistens beim Start) und lassen Sie es aktiv, bis Sie damit fertig sind.Ja. Es ist sinnvoll,
ExecutorService
wichtige Phasen wie das Beenden von Anwendungen usw. herunterzufahren .Angenommen, dies
ExecutorService
wird für verschiedene Aktivitäten in Ihrer Anwendung freigegeben. Jede Aktivität wird in unterschiedlichen Zeitintervallen angehalten / fortgesetzt, und dennoch benötigen Sie eineExecutorService
pro Anwendung.ExecutorService
Verschieben Sie die ExecutorService-Verwaltung (Erstellung / Herunterfahren) in Ihren benutzerdefinierten Service, anstatt den Status der Aktivitätslebenszyklusmethoden zu verwalten .Erstellen Sie
ExecutorService
in Service =>onCreate()
und fahren Sie es ordnungsgemäß herunteronDestroy()
Empfohlene Art des Herunterfahrens
ExecutorService
:So beenden Sie Java ExecutorService ordnungsgemäß
quelle
Nachschlagewerk
Chaper: 14 Seite: 814
quelle
Grund für den Aufruf von shutdown () in ExecutorService
Heute bin ich auf eine Situation gestoßen, in der ich warten muss, bis eine Maschine bereit ist, bevor ich eine Reihe von Aufgaben auf dieser Maschine starte.
Ich rufe diesen Computer erneut an. Wenn ich 503 (Server nicht verfügbar) nicht erhalte, ist der Computer bereit, meine Anforderungen zu verarbeiten. Also warte ich, bis ich 200 (Erfolg) für den ersten REST-Aufruf erhalte.
Es gibt mehrere Möglichkeiten, dies zu erreichen. Ich habe ExecutorService verwendet, um einen Thread zu erstellen, und die Ausführung nach jeweils X Sekunden geplant. Also muss ich diesen Thread unter einer Bedingung stoppen, check this out ...
final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); Runnable task = () -> { try { int statusCode = restHelper.firstRESTCall(); if (statusCode == 200) { executor.shutdown(); } } catch (Exception e) { e.printStackTrace(); } }; int retryAfter = 60; executor.scheduleAtFixedRate(task, 0, retryAfter, TimeUnit.SECONDS);
Zweite Nebenfrage, etwas kleiner befasst sich mit Android-Plattform.
Vielleicht kann ich antworten, wenn Sie etwas mehr Kontext bereitstellen! Auch aus meiner Erfahrung mit der Android-Entwicklung ist es selten, dass Sie Threads benötigen. Entwickeln Sie ein Spiel oder eine App, die Threads für die Leistung benötigt? Wenn nicht, haben Sie in Android andere Möglichkeiten, um Probleme zu lösen, wie das oben erläuterte Szenario. Sie können TimerTask, AsyncTask oder Handler oder Loader je nach Kontext verwenden. Dies liegt daran, dass Sie wissen, was passiert, wenn UIThread lange wartet: /
quelle
Dies gilt ungeachtet für geplante Unternehmen, z. B. für einen ScheduledExecutorService: Neue Fälle der gebuchten Aufgabe werden nicht ausgeführt.
Wir sollten erwarten, dass Sie eine Komfortanwendung haben, bei der eine Agentenverwaltung N Besorgungen ausführt.
Ich verstehe nicht, dass es mühelos bedeutet? Möglicherweise muss Ihre Bewerbung nicht die Option haben, weitere Aufträge an die Agentenverwaltung zu senden, und in der Zwischenzeit müssen Sie fest sitzen, damit Ihre aktuellen N-Verpflichtungen abgeschlossen sind.
Außer wenn Sie sich absolut sicher sind, dass Ihre Besorgungen am Ende erledigt sind, sollten Sie für eine bestimmte Pause fest sitzen und danach einfach aussteigen und die laufenden Saiten verlassen.
Für den Fall, dass Ihre Aktivitäten auf Störungen reagieren sollen, funktioniert dies einwandfrei.
Eine weitere interessante Situation ist der Punkt, an dem Sie einen ScheduledExecutorService haben, der eine Aktivität ausführt.
Der beste Weg, um die Aktivitätskette zu stoppen, besteht darin, shutdown () aufzurufen.
quelle