2009-03-06 12 views
8

Quiero escribir un daemon de línea de comandos que se ejecute para siempre. Entiendo que si quiero que la JVM pueda desconectarse correctamente en Linux, se debe ajustar la rutina de arranque mediante algún código C. Creo que estaré bien con un gancho de cierre por ahora.¿Future.get() es un reemplazo para Thread.join()?

a mis preguntas:

  1. Mi principal ([] String) bloque disparar un superdemonio separada.
  2. El Superdaemon sondeará y repetirá para siempre.

Así que normalmente lo haría:

class Superdaemon extends Thread { ... } 

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

     t.join(); 
    } 
} 

Ahora que pensé que si empezaba superdemonio a través de un ejecutor, no puedo hacer

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

f.get(); 

Es Future.get() implementado con Thread.join() ? Si no, ¿se comporta de manera equivalente?

Saludos,

Ashitaka

Respuesta

12

Sí, la forma en que las ha escrito es equivalente.

Sin embargo, realmente no necesita esperar a que se complete el subproceso Superdaemon. Cuando el hilo principal termina de ejecutar main(), ese hilo sale, pero la JVM no lo hará. La JVM seguirá ejecutándose hasta que la última cadena que no sea daemon salga de su método de ejecución.

Por ejemplo,

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

Verá la salida:

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

En otras palabras, el hilo principal termina primero, y luego el hilo secundaria completa y las salidas de JVM.

0

Sort'a. Future.get() es para que un hilo se dispare y calcule algo y luego lo devuelva al hilo de llamada de forma segura. Funcionaría si el get nunca regresó. Pero, me quedaría con la llamada join ya que es más simple y sin sobrecarga de Executer (no es que hubiera mucho).

Editar

Parece que ExecutorService.submit(Runnable) se pretende hacer exectly lo que estás tratando. Simplemente devuelve null cuando finaliza el Runnable. Interesante.

+0

El problema es que libros como JCIP recomiendan que usemos ejecutores para iniciar subprocesos. Por lo tanto, hago mi mejor esfuerzo para no utilizar Thread.start(). No estoy seguro de si elegiría necesariamente una forma particular de hacer las cosas simplemente basada en la simplicidad. Debe haber una razón más convincente, ¿no? – ashitaka

1

Future.get() obtendrá la respuesta futura de una llamada asincrónica. Esto también se bloqueará si la llamada aún no se ha completado. Es muy parecido a una unión de hilo.

http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/Future.html

+0

Similar, aunque parece que "también" volverá a lanzar cualquier excepción no detectada, también: http://abd-tech.blogspot.com/2011/09/throw-exception-from-java-thread-and.html – rogerdpack

6

La cuestión es que libros como JCIP está abogando por que usamos Ejecutores para los que parten los hilos. Por lo tanto, hago mi mejor esfuerzo para no utilizar Thread.start(). No estoy seguro de si elegiría necesariamente una forma particular de hacer las cosas simplemente basada en la simplicidad. Debe haber una razón más convincente, ¿no?

La razón convincente para utilizar java.util.concurrent es que la programación multi-hilo es muy complicado. Java ofrece las herramientas para eso (Threads, y volátiles palabras clave volátiles), pero eso no significa que pueda usarlas de manera segura sin dispararse en el pie: o bien demasiada sincronización, lo que resulta en cuellos de botella y puntos muertos innecesarios , o demasiado menos, lo que resulta en un comportamiento errático debido a las condiciones de carrera).

Con java.util.concurrente obtienes un conjunto de utilidades (escritas por expertos) para los patrones de uso más comunes, que puedes usar sin preocuparte de que tengas las cosas de bajo nivel correctas.

En su caso particular, sin embargo, no lo acabo de ver por qué necesita un hilo separado en absoluto, que también podría utilizar la principal:

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

Ejecutores son para tareas que desea se ejecuta en segundo plano (cuando tiene múltiples tareas paralelas o cuando su hilo actual puede continuar haciendo otra cosa).

Cuestiones relacionadas