Das Beenden der Anwendung dauert sehr lange

8

Wir haben eine Konsolenanwendung geschrieben (wird als Dienst verwendet), die mehrere Worker-Threads zum Behandeln von Anfragen, die über mina eingehen, startet. Die Anwendung verlässt die Hauptschleife, wenn ein Stoppsignal an einem bestimmten Netzwerkanschluss empfangen wird. Dies ist der beabsichtigte Weg, den Dienst zu stoppen. Das funktioniert ganz gut, aber wenn das Stoppsignal empfangen wird, wird der Prozess der Anwendung nicht sofort beendet (dauert bis zu 5 Minuten). Wir haben über Protokollmeldungen verifiziert, dass die Hauptfunktion schnell und wie erwartet verlassen wird und alle von der Anwendung erzeugten Threads ebenfalls beendet werden. Aber die Anwendung läuft weiter.

Die noch laufenden Threads vor Verlassen der Hauptfunktion sind:

%Vor%

Wir verwenden derzeit die folgende Java-Version:

%Vor%

Das Betriebssystem ist ubuntu 14.04 LTS.

Ich habe keine Ahnung von diesem Verhalten und hoffe auf einige Hinweise, wie ich dieses Problem weiter untersuchen kann.

Zusätzliche Informationen

Ich habe wie vorgeschlagen einen vollständigen Thread-Dump erstellt. Vier Threads warten:

%Vor%

Kann mir jemand bestätigen, dass ich nach pool-2-thread-1 forschen sollte? Ich bin mir nicht sicher, wie ich das Ergebnis interpretiere.

Lösung Am Ende hat ein Aufruf von acceptor.dispose (MINA) den Trick gemacht ...

    
user331471 08.05.2015, 09:32
quelle

1 Antwort

5

Ich vermute, Sie haben einen ExecutorService erstellt, der als Nicht-Daemon ausgeführt wird. Das heißt, wenn Sie shutdown() diesen Pool nicht beibehalten, wird die Anwendung so lange ausgeführt, bis der Thread ordnungsgemäß beendet wird (wie es für einige Minuten verwendet wurde)

Sie können einen ExecutorService mit Daemon-Threads erstellen, um zu verdeutlichen, dass die Anwendung nicht auf das Beenden dieses Thread-Pools warten muss. (Oder Sie können es explizit herunterfahren)

%Vor%
  

pool-2-thread-1 ist nichts, was wir absichtlich erstellt haben

Dies könnte von einer Bibliothek erstellt werden, aber es folgt der Form eines ExecutorService. Hinweis: pool-2.. gibt an, dass es sich nicht um den ersten Pool handelt, den die Anwendung erstellt.

Sie können Nicht-System-Threads erzwingen, indem Sie System.exit(0); verwenden. Dies ist nicht ideal, da die Threads möglicherweise nützliche Arbeit leisten, wenn sie aus einem guten Grund nicht-daemon gemacht wurden, aber wenn der Thread von einer dritten gestartet wird Party-Bibliothek, könnte es Ihre einfachste Option sein.

Etwas, das Sie versuchen könnten, ist die Verfolgung, wo alle Threads erstellt werden. Eine Möglichkeit besteht darin, den Debugger zu verwenden, um den Konstruktor der ThreadPoolExecutor - oder einer anderen Schlüsselmethode, die Ihnen anzeigen würde, wo der Pool erstellt wird, aufzulösen.

Oder Sie können einen Speicherprofiler mit Zuordnungsverfolgung verwenden. Dann schau dir an, wo jedes Thread-Objekt erstellt wird.

Eine weitere Option besteht darin, die Thread-Klasse so zu ändern, dass sie eine Stack-Ablaufverfolgung enthält, in der sie erstellt oder gestartet wurde. Dazu können Sie eine eigene Version erstellen und sie dem Boot-Klassenpfad voranstellen.

    
Peter Lawrey 08.05.2015, 09:43
quelle

Tags und Links