2009-03-06 14 views
8

Voglio scrivere un demone da riga di comando che gira per sempre. Capisco che se voglio che la JVM sia in grado di spegnersi con grazia in linux, è necessario avvolgere il bootstrap tramite un codice C. Penso che per ora sarò d'accordo con un gancio di chiusura.È Future.get() un sostituto per Thread.join()?

On alle mie domande:

  1. mio principale ([] String) blocco scatterà fuori un superdemone separata.
  2. Il SuperDemon eseguirà il polling e il ciclo continuo.

Così normalmente vorrei fare:

class Superdaemon extends Thread { ... } 

class Bootstrap 
{ 
    public static void main(String[] args) 
    { 
     Thread t = new Superdaemon(); 
     t.start(); 

     t.join(); 
    } 
} 

Ora ho pensato che se ho iniziato superdemone tramite un esecutore, posso fare

Future<?> f = exec.submit(new Superdaemon()); 

f.get(); 

È Future.get() implementato con Thread.join() ? In caso contrario, si comporta in modo equivalente?

saluti,

Ashitaka

risposta

12

Sì, il modo in cui li hai scritti è equivalente.

Tuttavia, non è necessario attendere il completamento del thread di SuperDemon. Quando il thread principale termina l'esecuzione di main(), quel thread termina, ma la JVM non lo farà. La JVM continuerà a essere in esecuzione fino a quando l'ultimo thread non demone esce dal suo metodo di esecuzione.

Per esempio,

public class KeepRunning { 
    public static void main(String[] args) { 
    Superdaemon d = new Superdaemon(); 
    d.start(); 
    System.out.println(Thread.currentThread().getName() + ": leaving main()"); 
    } 
} 

class Superdaemon extends Thread { 
    public void run() { 
    System.out.println(Thread.currentThread().getName() + ": starting"); 
    try { Thread.sleep(2000); } catch(InterruptedException e) {} 
    System.out.println(Thread.currentThread().getName() + ": completing"); 
    } 
} 

Vedrete l'output:

main: leaving main() 
Thread-0: starting 
Thread-0: completing 

In altre parole, il thread principale finisce prima, poi il thread secondario completa e le uscite JVM.

0

Sort'a. Future.get() è per avere un thread andare fuori e calcolare qualcosa e quindi restituirlo al thread chiamante in modo sicuro. Funzionerebbe se lo get non fosse mai restituito. Ma rimango con la chiamata join in quanto è più semplice e senza sovraccarico di Executer (non che ci sarebbe molto di più).

Modifica

Sembra ExecutorService.submit(Runnable) è destinato a fare exectly quello che stai cercando. Restituisce solo null quando lo Runnable viene completato. Interessante.

+0

Il problema è che libri come JCIP stanno sostenendo che usiamo Executors per avviare Threads. Quindi sto facendo del mio meglio per non utilizzare Thread.start(). Non sono sicuro di dover necessariamente scegliere un modo particolare di fare le cose semplicemente sulla base della semplicità. Ci deve essere una ragione più convincente, no? – ashitaka

6

Il problema è che libri come JCIP sta sostenendo che usiamo Esecutori per inizio Fili. Quindi sto facendo del mio meglio per non utilizzare Thread.start(). Non sono sicuro di dover necessariamente scegliere un modo particolare di fare le cose semplicemente sulla base della semplicità. Ci deve essere una ragione più convincente, no?

La ragione convincente per utilizzare java.util.concurrent è che la programmazione multi-thread è molto difficile. Java offre gli strumenti per farlo (Threads, sincronizzato e volatile parole chiave), ma ciò non significa che puoi tranquillamente usarli direttamente senza spararti ai piedi: o troppa sincronizzazione, con conseguente colli di bottiglia e deadlock inutili , o troppo meno, con conseguente comportamento irregolare a causa delle condizioni di gara).

Con java.util.contemporaneamente si ottiene un insieme di utilità (scritte da esperti) per i modelli di utilizzo più comuni, che è possibile utilizzare senza preoccuparsi di avere le cose di basso livello corrette.

Nel vostro caso particolare, però, non del tutto a capire perché avete bisogno di un thread separato a tutti, si potrebbe anche utilizzare il principale:

public static void main(String[] args) 
{ 
    Runnable t = new Superdaemon(); 
    t.run(); 
} 

Esecutori sono pensati per le attività che si desidera eseguire in background (quando si hanno più attività parallele o quando il thread corrente può continuare a fare qualcos'altro).

Problemi correlati