2011-12-29 14 views
27

Scenario ipotetico:
Ho un thread daemon responsabile di alcuni I/O, il thread principale termina e restituisce e JVM decide di terminare il mio thread daemon.In che modo JVM termina i thread del daemon? o Come scrivere thread daemon che terminano con grazia

Come funziona? Interrompere? Finalizzare? Come posso codificare il mio thread daemon in modo che reagisca con grazia quando viene terminato?

+1

Hai guardato il codice sorgente? –

+2

@StephenC Questo non mi è mai venuto in mente e fornirebbe sicuramente una risposta definitiva (sebbene non sia necessariamente utile). Personalmente, tuttavia, non sono abbastanza coraggioso da tentare di farlo e non mi aspetto davvero nessun altro. –

+0

Va bene, fammi essere più esplicito. Il modo migliore per rispondere a una domanda come questa è guardare il codice sorgente, o almeno il codice Java. In generale è facile da leggere e ben commentato.(E non riesco a capire come una risposta definitiva a una domanda sia meno utile di una non definitiva ... specialmente se * tu * fosse la persona che legge il codice!) –

risposta

10

ho appena scritto il seguente codice come un test:

public class DaemonThreadPlay { 
    public static void main(String [] args) { 
     Thread daemonThread = new Thread() { 
      public void run() { 
       while (true) { 
        try { 
         System.out.println("Try block executed"); 
         Thread.sleep(1000l); 
        } catch (Throwable t) { 
         t.printStackTrace(); 
        } 
       } 
      } 

      @Override 
      public void finalize() { 
       System.out.println("Finalize method called"); 
      } 
     }; 
     daemonThread.setDaemon(true); 
     daemonThread.start(); 

     try { 
      Thread.sleep(2500l); 
     } catch (Throwable t) { 
      //NO-OP 
     } 
    } 
}  

ho messo i punti di interruzione nel blocco catch del filo demone e nel metodo di finalizzazione. Nessun punto di interruzione è stato raggiunto anche se il blocco try è stato eseguito. Ovviamente questo codice ha problemi di sincronizzazione/temporizzazione, ma penso che possiamo tranquillamente concludere che i thread daemon non sono interrotti allo shutdown, né i loro metodi finalize() necessariamente invocati.

È sempre possibile aggiungere un gancio di arresto alla JVM Durata:

Thread shutdownHook = ... // construct thread that somehow 
          // knows about all the daemon threads 
Runtime.getRuntime().addShutdownHook(shutdownHook); 

vostro gancio di arresto può ovviamente fare tutto ciò che le attività sono necessarie per un arresto "graziosa".

+1

Mi piace il gancio di arresto. –

+0

Trovato [questo] (http://stackoverflow.com/questions/1323408/get-a-list-of-all-threads-currently-running-in-java/3018672#3018672) quando si cercano modi per ottenere thread attivi . Dovrebbe scorrere iterazione su array per verificare almeno un thread utente.
Penso che un hook di arresto sia la soluzione migliore, mai conosciuta prima di questa funzionalità. Penso che terrò un riferimento al mio hook di shutdown nella mia classe Main e manterrò una collezione dei miei thread daemon nel hook di shutdown. Quindi posso semplicemente interromperli tutti. Proverò a pubblicare il mio codice una volta che lo implementerò. –

+2

Se si chiama 'System.gc()' esplicitamente e l'opzione JVM '-XX: + DisableExplicitGC' non è impostata, il thread daemon si chiuderà. Ciò significa che Garbage Collector è responsabile della chiusura dei thread del daemon al termine di tutti i thread dell'utente. – George

4

AFAIK, i thread Daemon non sono realmente utili per il lavoro di I/O del flusso principale. Se tutti i thread sono completati, JVM potrebbe chiudere bruscamente tutti i thread del daemon. L'eventuale lavoro intorno per il requisito sarà creare un ExecutorService come di seguito:

ExecutorService execPool = Executors.newSingleThreadExecutor(new ThreadFactory() { 

    @Override  
    public Thread newThread(Runnable runnable) {  
     Thread thread = Executors.defaultThreadFactory().newThread(runnable); 
     thread.setDaemon(true); 
     return thread;  
    } 
}); 

invocano metodo shutdown ExecutorService dal gancio di arresto.

Runtime.getRuntime().addShutdownHook(....) 
+0

il tuo nuovo metodo Thread crea infatti un nuovo thread factory ogni volta. una chiamata a 'Executors.defaultThreadFactory()' restituisce semplicemente un 'nuovo DefaultThreadFactory()' – benez

1

uso di interruzione e unisciti:

class Daemon extends Thread { 
    public void run() { 
     while (true) { 
      try { 
       Thread.sleep(1000); 
      } catch (InterruptedException e) { 
       System.out.println(e); 
       break; 
      } 
     } 
     System.out.println("exit run()"); 
    } 
} 
public class So8663107 { 
    public static void main(String[] arguments) throws InterruptedException { 
     System.out.println(Thread.activeCount()); 
     Daemon daemon = new Daemon(); 
     daemon.setDaemon(true); 
     daemon.start(); 
     Thread.sleep(2500); 
     System.out.println(Thread.activeCount()); 
     daemon.interrupt(); 
     daemon.join(); 
     System.out.println(Thread.activeCount()); 
    } 
} 
+3

Non penso che tu abbia capito la domanda. Non voglio interrompere il mio thread daemon. Voglio sapere come la JVM le termina e come affrontarla. –

+0

scusate, stavo tentando di rispondere: "Come posso codificare il mio thread daemon in modo che termini con grazia?" –

+0

Ok, ho modificato la domanda –

5

penso che fraintendere ciò che un thread demone è.

Vedi what is a daemon thread in java

In sintesi, significa in sostanza che un thread demone non dovrebbe fare qualsiasi I/O o tenendo tutte le risorse. Se stai violando questa regola di base, la tua discussione non si qualifica come thread daemon.

L'aggiunta di un gancio di arresto è il modo standard per garantire il codice viene invocato prima della risoluzione JVM, ma anche questo non è garantita al 100% - la tua JVM potrebbe bloccarsi per esempio, lasciando il sistema operativo per riordinare le risorse in maniera che protegge il sistema operativo, ma molto probabilmente lascia la tua applicazione in uno stato incoerente/errato.

I meccanismi di checkpoint e ripristino del sistema risalgono ai primi giorni del software (ad esempio sistemi operativi e operazioni batch) e, purtroppo, questa ruota continua a essere reinventata perché non esiste un approccio "silver bullet" (API) che affronta questo problema in modo abbastanza generico.

+0

Qual è la base per affermare che i thread Daemon non dovrebbero fare IO o contenere risorse? – ykaganovich

+0

Segui il link fornito e otterrai alcuni approfondimenti. – user924272

+1

scusate, non sono d'accordo. Finché si capisce che un thread Daemon può essere eliminato a metà elaborazione, non c'è pericolo, a meno che tu non sappia qualcosa sulle perdite di risorse Java. – ykaganovich

Problemi correlati