Domanda

Voglio scrivere un demone della riga di comando che funziona per sempre. Capisco che se voglio che JVM sia in grado di spegnersi con grazia in Linux, è necessario avvolgere il bootstrap tramite un codice C. Penso che per ora starò bene con un hook di spegnimento.

Alle mie domande:

  1. Il mio blocco principale (String []) attiverà un Superdaemon separato.
  2. Il Superdaemon eseguirà il polling e il loop per sempre.

Quindi normalmente farei:

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 avessi avviato Superdaemon tramite un Executor, posso farlo

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

f.get();

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

Saluti,

Ashitaka

È stato utile?

Soluzione

Sì, il modo in cui le hai scritte è equivalente.

Tuttavia, non è necessario attendere il completamento del thread Superdaemon. Quando il thread principale termina l'esecuzione di main (), quel thread viene chiuso, ma JVM no. La JVM continuerà a funzionare fino a quando l'ultimo thread non daemon esce dal suo metodo di esecuzione.

Ad 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");
  }
}

Vedrai l'output:

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

In altre parole, il thread principale termina per primo, quindi il thread secondario viene completato e la JVM viene chiusa.

Altri suggerimenti

  

Il problema è che libri come JCIP stanno sostenendo che usiamo Executors per avviare Thread. Quindi sto facendo del mio meglio per non usare Thread.start (). Non sono sicuro che sceglierei necessariamente un modo particolare di fare le cose basandomi solo sulla semplicità. Ci deve essere una ragione più convincente, no?

La ragione convincente di usare java.util.concurrent è che la programmazione multi-thread è molto complicata. Java offre gli strumenti per questo (Thread, le parole chiave sincronizzate e volatili ), ma ciò non significa che puoi usarli in sicurezza direttamente senza spararti ai piedi: O troppa sincronizzazione, con conseguenti colli di bottiglia e deadlock non necessari, o troppo meno, con conseguente comportamento irregolare a causa delle condizioni di gara).

Con java.util.concurrent ottieni una serie di utility (scritte da esperti) per i modelli di utilizzo più comuni, che puoi semplicemente usare senza preoccuparti di avere le cose di basso livello giuste .

Nel tuo caso particolare, tuttavia, non capisco perché hai bisogno di un thread separato, potresti anche usare quello principale:

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

Gli 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).

Future.get () otterrà la risposta futura da una chiamata asincrona. Questo bloccherà anche se la chiamata non è stata ancora completata. È molto simile a un thread thread.

http: // java .sun.com / J2SE / 1.5.0 / docs / api / java / util / concorrente / Future.html

Sort'a. Future.get () serve per far partire un thread e calcolare qualcosa, quindi restituirlo al thread chiamante in modo sicuro. Funzionerebbe se il get non fosse mai tornato. Ma continuerei con la chiamata join in quanto è più semplice e senza sovraccarico di Executer (non che ci sarebbe così tanto).

Modifica

Sembra ExecutorService.submit (Runnable) ha lo scopo di fare esattamente ciò che stai tentando. Restituisce null al completamento di Runnable . Interessante.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top