2009-07-31 9 views
9

Według współdziałania Java Briana Goetza w praktyce JVM nie może wyjść, dopóki wszystkie wątki (nondaemon) nie zostaną zakończone, więc nieudane zamknięcie Executora może uniemożliwić wyjście JVM.Jak zamknąć wszystkie Executory podczas zamykania aplikacji?

tj. System.exit (0) niekoniecznie działa zgodnie z oczekiwaniami, jeśli w pobliżu znajdują się Executory. wydaje się konieczne, aby umieścić jakąś

public void stop() { exec.shutdown() } 

metod do wszystkich klas, które zawierają Executory, a następnie połączyć je, gdy aplikacja ma się zakończyć. Czy to jedyny sposób, czy jest jakiś skrót do wyłączenia wszystkich Egzekutorów?

+0

Byłem mylący Executor z Runnable. Usunąłem odpowiedź, ponieważ nie ma to większego sensu. @skaffman ma mój głos. –

Odpowiedz

14

Nie ma skrótów do ich wszystkich, nie. Powinieneś również zadzwonić pod numer shutdownNow() zamiast shutdown(), w przeciwnym razie możesz poczekać chwilę.

To, co możesz zrobić, jak przypuszczam, to kiedy tworzysz Executora, rejestrujesz go w centralnym miejscu. Następnie, po wyłączeniu, wystarczy zadzwonić pod numer shutdown() na ten obiekt centralny, który z kolei może zakończyć każdy z zarejestrowanych executorów.

Jeśli używasz Spring, możesz skorzystać z jego fasoli fabrycznej, która tworzy i zarządza Executorami. Obejmuje to zamykanie ich z wdziękiem po zamknięciu aplikacji i oszczędzanie konieczności samodzielnego zarządzania nimi.

+0

Centralny rejestr wydaje się być rozsądną opcją. Zabawne, że java.util.concurrent nie zawiera takich. –

+0

Szkoda też, że Executory to tylko statyka, która utrudnia ukrywanie jej za interfejsem rejestracyjnym bez duplikowania kilkudziesięciu podpisów metod. – skaffman

+0

Mam również podobny problem. Nie używam jawnie ScheduledThreadPoolExecutor. Więc nie mam żadnego centralnego odniesienia do tego samego. W takim przypadku, jak uzyskać dostęp do tych wątków? Próbuję z wdziękiem zamknąć je w metodzie ContextDestroyed – DecKno

0

Prawdopodobnie chciał powiedzieć, że JVM nie może się zatrzymać, dopóki wątki nondaemon nie zostaną ukończone. To jak uruchamianie prostej klasy z polecenia jak java SomeClass i po wykonaniu głównej metody JVM zatrzymuje się.

System.exit jest poleceniem zakończenia JVM, nawet jeśli wątki demona są uruchomione JVM zostanie zamknięte.

+1

Jak napisał Goetz, wątki * nondaemon * mogą uniemożliwić wyjście JVM. Właściwie to doświadczyłem tego. Debugger pokazuje, że aplikacja może zablokować system.exit (0) w nieskończoność, ale wydaje się, że jest to zachowanie niedeterministyczne. Zwykle nie zacina się, ale czasami tak się dzieje. –

5

Można również podać implementację ThreadFactory, która oznacza utworzone wątki jako wątki demona. Preferuję mechanizm czystego zamknięcia (z metodami cyklu życia), ale są przypadki, w których nie potrzebujesz gwarancji co do stanu/ukończenia niezakończonych zadań, kiedy to może być właściwe.

+0

Dzięki za wskazanie tej opcji. W rzeczywistości niektóre z moich executorów powinny być wątkami demona, po prostu nie są demoniczne, ponieważ to właśnie wykonują domyślnie Executors.newXXXExecutor(): s. –

7

Domyślnie Executor tworzy tylko wątki nie będące demonami. Możesz to zmienić, dostarczając Executorowi swój własny ThreadFactory. Oto przykład:

class DaemonThreadFactory implements ThreadFactory { 
    public Thread newThread(Runnable r) { 
    Thread t = new Thread(r); 
    t.setDaemon(true); 
    return t; 
    } 
} 

Bądź ostrożny, chociaż, ponieważ JVM wyjdzie razu nawet jeśli te wątki są zajęte wykonuje pożyteczną pracę!

8

Udekoruj wykonawcę z com.google.common.util.concurrent.MoreExecutors#getExitingExecutorService

@Beta 
public static ExecutorService getExitingExecutorService(ThreadPoolExecutor executor, 
             long terminationTimeout, 
             TimeUnit timeUnit) 

Przekształca dany ThreadPoolExecutor się z ExecutorService że wychodzi, gdy wniosek jest kompletny. Robi to, używając wątków demona i dodając hak zamykający, czekając na ich zakończenie.

Dotyczy to głównie stałych pul wątków. Zobacz Executors.newFixedThreadPool (int).

Powiązane problemy