2012-10-31 8 views
8

Ich versuche, einen Shutdown-Hook auf meinem Ubuntu-Server zu arbeiten, aber ich habe ein Problem mit mehr als einem Thread. Mit dem grundlegenden ShutdownHook funktioniert das folgende Codebeispiel, wenn ich den Prozess unter Verwendung von kill <PID> abbricht, was bedeutet, dass das Abschaltverhalten aktiviert ist.Java Shutdown-Hook mit mehr als einem Thread

public static void main(String[] args) { 
    ShutdownHook shutDown = new ShutdownHook(); 
    shutDown.attachShutDownHook(); 

    while(true){} 
} 

jedoch dieser gleiche Code mit einem zusätzlichen Faden nicht

public static void main(String[] args) { 
    ShutdownHook shutDown = new ShutdownHook(); 
    shutDown.attachShutDownHook(); 

    (new Thread() { 
     public void run() { 
      while (true) {} 
     } 
    }).start(); 

    while(true){} 
} 

Irgendwelche Ideen?

class ShutdownHook { 

    ShutdownHook() { 
    } 

    public void attachShutDownHook() { 

      Runtime.getRuntime().addShutdownHook(new Thread() { 
        @Override 
        public void run() { 
          System.out.println("Shut down hook activating"); 
        } 
      }); 
      System.out.println("Shut Down Hook Attached."); 

    } 
} 
+0

Wie ist das Verhalten mit dem zweiten Thread? Stoppen Sie die Anwendung, ohne das Abschaltverhalten aufzurufen? Du sagst auch "Töte den Prozess". Was meinst du damit? Wie beendest du es? – Gray

+0

Der zweite Thread ist nur ein Beispiel für einen Live-Thread. In meinem aktuellen Beispiel lauscht es auf Verbindungen an einem Port und bleibt während der gesamten Lebensdauer des Programms am Leben. Ich beende den Prozess mit 'kill '. Das zweite Programm oben funktioniert nicht so wie es ist, also fehlt mir etwas in Bezug auf mehr als einen Thread – Reese

+0

Versuchen Sie 'jstack ' an zu laufen, nachdem Sie 'kill' aufgerufen haben, um zu sehen, welche Threads noch laufen. – SimonC

Antwort

0

java.lang.Runtime.addShutdownHook(Thread) registriert einen neuen Shutdown-Hook virtuelle Maschine:

Die virtuelle Java-Maschine schaltet in Reaktion auf zwei Arten von Ereignissen nach unten:

  • Das Programm normalerweise verläßt, wenn der letzte Nicht-Daemon-Thread beendet wird oder wenn die Exit-Methode (äquivalent, System.exit) aufgerufen wird oder

  • Die virtuelle Maschine wird als Reaktion auf einen Benutzerinterrupt beendet, z. B. ^ C eingeben oder ein systemweites Ereignis wie Benutzerabmeldung oder Herunterfahren des Systems.

Ihr Code läuft auf unbestimmte Zeit, so dass der Shutdown-Hook wird nie aufgerufen werden.

[Nach dem Bearbeiten]

Welche kill verwenden Sie?

kill -9 ist nicht auffangbar

kill -2 verwendet werden, um eine Abfrage-c (SIGINT)

+0

Ich benutze 'kill ' ohne zusätzliche Argumente. Es sollte abfangbar sein, und in der Tat funktioniert in dem Szenario mit einem Thread – Reese

3

JVM nicht Ausgang zu emulieren, während es noch ausgeführt werden, nicht-Daemon-Threads. Versuchen Sie, setDaemon(true) auf Ihrem neuen Thread aufzurufen.

+0

Dies scheint nicht den Trick zu tun – Reese

1

Um ein Beispiel aus einem eigenen Projekt zu nehmen;

Meine Kernklasse erzeugt eine ganze Reihe von Worker-Threads, die Worker führen Transaktionen aus, die abgeschlossen werden müssen.

In der Kernklasse habe ich;

Runtime.getRuntime().addShutdownHook(new ShutdownCleanup()); 

Das sieht ungefähr so ​​aus;

public final class ShutdownCleanup extends Thread() { 
    public void run() { 
     log("waiting for worker threads to finish..."); 
     while(WorkerThread.transactionInProgress()) { 
      Thread.sleep(1000); 
     } 
     //close various sockets and resources 
    } 
} 

Der Moment, als ich Ctrl+C im Terminal getroffen, erscheint die Meldung log. Der Shutdown-Shutdown wird also sofort aktiviert. Er wird nicht ausgeführt, sobald das Programm zum Sterben bereit ist. Stattdessen wird es ausgeführt, sobald die Anforderung zum Schließen oder zum Beenden empfangen wird.

Aus diesem Grund glaube ich, was andere über heruntergefahrene Hooks gesagt haben, die niemals aufgerufen werden, solange noch ein Thread am Leben ist, ist falsch.Was wäre der Sinn eines Shutdown-Hooks, der erst aktiviert wird, wenn alles schon tot ist?

Es kann sein, dass Sie eine harte Tötung verwenden, z. B. -9. Haben Sie eine normale Abschaltung mit Ctrl+C oder SIGINT versucht?

+0

Ja habe ich 'kill ' ohne Argumente und 'STRG + C' versucht. Beide arbeiten im ersten Beispiel mit einem einzelnen Thread und keiner funktioniert, sobald ich mehr als einen Thread habe. Vielleicht etwas, das mir fehlt, wenn ich meinen Thread aufstelle? – Reese

+0

Haben Sie versucht, die "Runtime" -Methode oben zu verwenden? Ich habe keine Ahnung, welchen Unterschied es machen würde, aber vielleicht befestigst du einen Haken an einem Thread und nicht an der JVM ... wenn das möglich ist. – lynks

+0

Ich verwende Runtime. Ich habe meine ursprüngliche Frage aktualisiert, um das ShutdownHook selbst zu zeigen – Reese