9

W Tomcat, napisałem ServletContextListener który rozpocznie się ExecutorService podczas rozruchu i zakończenia go, gdy jest rozładowany.Wyłączanie się ExecutorService

Mam następujący przykład w javadoc dla ExecutorService

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

Moje pytanie brzmi mam propagować InterruptedException w metodzie contextDestroyed()?

+1

Czy twój executor jest zamknięty? Mój nie ma wątpliwości, że użyłem tego samego kodu ... (i wielu innych podejść) – SoulWanderer

+0

Mój nie zamyka się z tym samym kodem. Używam tomcat 7 – lili

Odpowiedz

4

Powiedziałbym, że nie. Metoda contextDestroyed jest wywoływana przez kontener jako powiadomienie, że kontekst ma zostać zburzony, nie pyta o pozwolenie. Ponadto Javadoc nie definiuje, co się stanie, jeśli wyrzucisz z niego wyjątek, więc wyniki mogą być nieprzewidywalne i/lub nieprzenośne.

Co mogę zrobić, to zadzwonić pod numer executor.shutdownNow() wewnątrz bloku catch, aby wymusić zakończenie executora (tzn. "Miałeś swoją szansę, teraz przestań").

+0

Jeśli jest "nieprzewidywalny", co jest najgorszą rzeczą, jaka może się stać, jeśli zostanie zgłoszony wyjątek? –

+0

+1 spot-on z poleceniem shutDownNow(). Pochłonięcie wyjątku i ustawienie flagi tutaj jest naprawdę słuszne. –

+0

Najgorszy przypadek: kod wykonujący to wywołanie zwrotne nie przechwytuje go i wątek ulega awarii. Co ważniejsze, pomyśl o tym, co wskazuje na wyjątek pochodzący z "waitAnitation()". Wszystkie wyjątki oznaczają, że wątek nie mógł kontynuować oczekiwania na zakończenie wszystkich wątków, ponieważ został przerwany przez inny wątek, co oznacza, że ​​powinien się zakończyć. Jeśli nie wykonałeś połączenia blokującego, flaga przerwań zostałaby ustawiona w tle i nawet byś o tym nie wiedział. Tak więc właściwą rzeczą jest ustawienie flagi, zakończenie executora i ustawienie flagi. –

1

Co masz w próbce kodu (ponowne przerwanie bieżącego wątku) jest dokładnie to, co polecam. Coś w Tomcacie poza twoim własnym kodem wysłało oryginalne przerwanie, więc pozwól Tomcatowi zaryzykować.

Nie wiem, co Tomcat zrobi z wyjątkiem InterruptedException. To nieokreślone. Ale Tomcat zainicjował przerwanie i Tomcat jest właścicielem wątku, którego używa metoda contextDestroyed (...). Ogólna zasada z "Java Concurrency in Practice", która dotyczy tutaj: twórca wątku jest odpowiedzialny za obsługę wątku- Problemy z cylce.

Obsługa przerwania jest z pewnością kwestią cyklu życia.

+0

Czy wiesz, co Tomcat zrobi z wyjątkiem InterruptedException? –

0

Zgadzam się ze Stevem, zresetowanie flagi przerwania daje kod poza kontrolą szansę zareagowania na zdarzenie.

Tempus Fugit-oferuje metodę convieance to zrobić dla Ciebie, wraz z explict wyjątkiem limitu czasu, jeśli coś trwa zbyt długo.

waitOrTimeout(shutdown(executor), timeout); 

Sprawdźcie w sekcji współbieżności z docs, jeśli jego zainteresowania ... tempusfugitlibrary.org/documentation

example ten demonstruje jej wykorzystania, zarówno w oczekiwaniu na zakończenie i bardziej agresywne wyłączył.