2009-07-31 4 views
9

Secondo Concurrency in Practice di Brian Goetz JVM non può essere terminato fino a quando tutti i thread (nondaemon) non sono terminati, quindi non riuscire a arrestare un Executor potrebbe impedire l'uscita dalla JVM.Come spegnere tutti gli Executor quando si esce da un'applicazione?

I.e. System.exit (0) non funziona necessariamente come previsto se ci sono Executor in giro. Sembrerebbe necessario mettere un qualche tipo di

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

metodi per tutte le classi che contengono Esecutori, e poi li chiamo quando l'applicazione è in procinto di terminare. È questo l'unico modo, o c'è una sorta di scorciatoia per chiudere tutti gli Executor?

+0

Stavo confondendo Executor con Runnable. Ho cancellato la mia risposta in quanto non ha molto senso. @ Skaffman ha il mio voto. –

risposta

14

Non esiste una scorciatoia per eseguirli tutti, no. Inoltre, dovresti probabilmente chiamare shutdownNow() anziché shutdown(), altrimenti potresti aspettare un po '.

Quello che potresti fare, suppongo, è quando crei l'Esecutore, registrarlo in un posto centrale. Quindi, al momento dello spegnimento, è sufficiente chiamare lo shutdown() su quell'oggetto centrale, che a sua volta potrebbe terminare ciascuno degli esecutori registrati.

Se si utilizza Spring, è possibile sfruttare i bean di fabbrica che creano e gestiscono gli Executor per conto dell'utente. Questo include chiuderli con grazia quando l'applicazione si chiude, e ti risparmia di doverli gestire da solo.

+0

Il registro centrale sembra essere un'opzione ragionevole. Divertente che java.util.concurrent non includa tale. –

+0

È anche un peccato che gli Executor siano solo un mucchio di statistiche, che rende difficile nasconderlo dietro un'interfaccia di registrazione senza duplicare diverse dozzine di firme di metodo. – skaffman

+0

Anche io sto affrontando un problema simile. Non sto usando in modo esplicito ScheduledThreadPoolExecutor. Quindi non ho alcun riferimento centrale allo stesso. In tal caso, come accedere a questi threadpool? Sto cercando di chiuderli con grazia nel metodo ContextDestroyed – DecKno

0

Probabilmente intendeva dire che JVM non può fermarsi da solo fino a quando i thread nondaemon non sono terminati. È come eseguire una semplice classe da comando come java SomeClass e dopo l'esecuzione del metodo principale, JVM si ferma.

System.exit è un comando di terminazione JVM, anche se i thread daemon sono in esecuzione, JVM verrà arrestato.

+1

Come ha scritto Goetz, i thread * nondaemon * possono impedire l'uscita di JVM. In realtà ho sperimentato questo. Debugger indica che l'app può bloccarsi su System.esci (0) all'infinito, ma sembra essere un comportamento non deterministico. Di solito non si inceppa, ma a volte lo fa. –

5

È inoltre possibile fornire un'implementazione di ThreadFactory che contrassegna i thread creati come thread daemon. Preferisco un meccanismo di arresto pulito (con i metodi del ciclo di vita), ma ci sono casi in cui non è necessario garantire lo stato/completamento di attività non completate quando questo può essere appropriato.

+0

Grazie per aver segnalato questa opzione. In realtà alcuni dei miei esecutori dovrebbero essere thread daemon, sono semplicemente dei non demoni perché è quello che Executors.newXXXExecutor(): s fa di default. –

7

Per impostazione predefinita, un Executor creerà solo thread non daemon. È possibile sovrascriverlo fornendo l'Executor con il proprio ThreadFactory. Ecco un esempio:

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

essere cauti, però, perché la JVM uscirà subito anche se questi fili sono occupati a fare un lavoro utile!

8

decorare l'esecutore con com.google.common.util.concurrent.MoreExecutors#getExitingExecutorService

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

converte le ThreadPoolExecutor in un ExecutorService che esce quando l'applicazione è completa. Lo fa usando i thread di daemon e aggiungendo un hook di shutdown per attendere il loro completamento.

Si tratta principalmente di pool di thread fissi. Vedi Executors.newFixedThreadPool (int).