2009-09-16 12 views
9

In Tomcat, schrieb ich eine ServletContextListener, die eine ExecutorService während des Starts starten und es beenden, wenn sie entladen ist.Ausschalten eines ExecutorService

Ich bin nach dem Vorbild in der javadoc für ExecutorService

public void contextDestroyed(ServletContextEvent sce) 
{ 
    executor.shutdown(); 
    try 
    { 
     executor.awaitTermination(50, TimeUnit.SECONDS); 
    } 
    catch(InterruptedException ie) 
    { 
     Thread.currentThread().interrupt(); 
    } 
} 

Meine Frage ist, sollte ich die InterruptedException im contextDestroyed() -Methode propagieren?

+1

Wird Ihr Executor geschlossen? Meines tut nicht alt Ich benutzte den gleichen Code ... (und viele weitere Ansätze) – SoulWanderer

+0

Mine schließt nicht mit dem gleichen Code. Ich benutze Tomcat 7 – lili

Antwort

4

Ich würde Nein sagen. Die Methode contextDestroyed wird vom Container als Benachrichtigung darüber, dass der Kontext abgerissen werden soll, aufgerufen und fragt nicht nach Ihrer Berechtigung. Außerdem definiert das Javadoc nicht, was passiert, wenn Sie eine Ausnahme auslösen, sodass die Ergebnisse möglicherweise nicht vorhersehbar und/oder nicht portabel sind.

Was ich tun würde, ist executor.shutdownNow() im catch-Block aufrufen, um den Executor zwangsweise zu beenden (d. H. "Sie hatten Ihre Chance, jetzt zu stoppen").

+0

Wenn es "unvorhersehbar" ist, was ist das Schlimmste, was passieren könnte, wenn eine Ausnahme ausgelöst wird? –

+0

+1 Spot-on mit der Empfehlung shutDownNow(). Die Ausnahme zu absorbieren und hier die Flagge zu setzen, ist wirklich das Richtige. –

+0

Im schlimmsten Fall fängt der Code, der diesen Callback ausführt, ihn nicht ab und ein Thread stürzt ab. Noch wichtiger jedoch, überlegen Sie, was die Ausnahme von "awaisttermination()" anzeigt. Die einzige Ausnahme besteht darin, dass der Thread nicht auf das Ende aller Threads warten konnte, da er von einem anderen Thread unterbrochen wurde, was darauf hinweist, dass er beendet werden sollte. Hätten Sie keinen blockierenden Anruf getätigt, wäre das Interrupt-Flag im Hintergrund gesetzt worden und Sie würden nicht einmal davon erfahren. Also ist es richtig, die Flagge zu setzen, den Executor zu beenden und die Flagge zu setzen. –

1

Was Sie in Ihrem Codebeispiel haben (wieder unterbrechen den aktuellen Thread) ist genau das, was ich empfehlen würde. Etwas in Tomcat außerhalb deines eigenen Codes hat den ursprünglichen Interrupt gesendet, also lass Tomcat eine Chance haben, damit umzugehen.

Ich weiß nicht, was Tomcat mit dem InterruptedException zu tun. Es ist undefiniert. Tomcat initiierte jedoch den Interrupt und Tomcat besitzt den Thread, in dem die contextDestroyed (...) -Methode ausgeführt wird. Der allgemeine Grundsatz von "Java Concurrency in Practice", der hier gilt, ist: Der Ersteller des Threads ist verantwortlich für die Thread-Lebensdauer. cycle-Probleme.

ein Interrupt-Behandlung ist auf jeden Fall eine Life-Cycle-Ausgabe.

+0

Wissen Sie, was Tomcat mit der InterruptedException machen wird? –

0

ich mit Steve einverstanden ist, den Interrupt-Flag Zurücksetzen Code außerhalb Ihrer Kontrolle gibt eine Chance, auf das Ereignis zu reagieren.

tempus-fugit bietet eine convieance Methode, dies zu tun für Sie, zusammen mit einer explict Timeout Ausnahme, wenn die Dinge zu lange dauern.

waitOrTimeout(shutdown(executor), timeout); 

Haben Sie einen Blick unter die Gleichzeitigkeit Abschnitt der docs, wenn sein von Interesse ... tempusfugitlibrary.org/documentation

Diese example seine Verwendung zeigt, sowohl für die Fertigstellung und aggressiver Abschaltung warten.