2012-05-26 18 views
8

Multi-threading en Java se hace definiendo run() e invocando start().¿Cómo funciona el método Java run()?

Iniciar delegados a un método nativo que inicia un hilo a través de las rutinas del sistema operativo y ejecutar() se invoca desde dentro de este hilo generado recientemente.

Cuando se inicia una aplicación independiente, se crea automáticamente una secuencia principal para ejecutar main().

Consideremos ahora el código -

public class Test extends Thread { 
    public static void main(String[] args) throws Exception { 
     new Thread(new Test()).start(); 
     throw new RuntimeException("Exception from main thread"); 
    } 
    public void run() { 
     throw new RuntimeException("Exception from child thread"); 
    } 
} 

Ésta es la salida -

java.lang.RuntimeException: Exception from child thread 
    at com.Test.run(Test.java:11) 
    at java.lang.Thread.run(Thread.java:662) 
java.lang.RuntimeException: Exception from main thread 
    at com.Test.main(Test.java:8) 

Si método main() se puso en marcha a través de un hilo por qué no se ejecuta() aparecerá en la parte superior de la jerarquía de invocación?

¿Cómo podría generarse el hilo principal sin implementar Runnable?

+0

Solo para aclarar lo que está preguntando: ¿su expectativa es que 'main()' se invoque de manera diferente cuando su clase propietaria implemente 'Runnable'? (Porque no lo es) – cheeken

Respuesta

4

No he mirado las partes internas de la JVM, pero supongo que la JVM instancia el hilo principal para ejecutar el método principal, pero ejecuta este hilo principal invocando código nativo directamente, sin pasar por el Java clásico clases y métodos para iniciar el hilo.

+0

justo en el objetivo :) +1 – mprabhat

3

JVM inicia el método principal en un subproceso separado, es el subproceso principal del subproceso secundario, por eso no ve el subproceso secundario en la parte superior de la jerarquía de invocación.

Por lo tanto, en su caso, JVM creó un subproceso que inició su programa, que también amplía el subproceso.

Luego, en su método principal creó una nueva instancia de su clase, llamada start on it, esto iniciará un nuevo hilo que es hijo de thread iniciado por JVM para iniciar su programa.

Dado que el método principal es un punto de partida para un programa java independiente, es responsabilidad de JVM iniciarlo en un hilo separado, no debe escribir código para él.

Al iniciar un programa llamando al método principal, JVM no necesita que sea un subproceso o implementar Runnable, es un procedimiento estándar.

Descripción de Inside Java Virtual Machine

El método main() de la clase inicial de una aplicación sirve como el punto de partida para el hilo inicial de esa aplicación. El subproceso inicial puede, a su vez, desencadenar otros subprocesos.

Dentro de la máquina virtual Java, los subprocesos vienen en dos sabores: daemon y no demonio. Un subproceso de daemon suele ser un subproceso utilizado por la propia máquina virtual , como un subproceso que realiza la recolección de basura. La aplicación, sin embargo, puede marcar cualquier subproceso que cree como subprocesos de daemon. El hilo inicial de una aplicación - el que comienza en main() - es un hilo que no es daemon.

Una aplicación Java continúa ejecutando (la instancia de la máquina virtual sigue viviendo), siempre y cuando todos los hilos no demonio siguen siendo ejecución. Cuando todos los subprocesos no daemon de una aplicación Java finalicen, se cerrará la instancia de la máquina virtual. Si el administrador de seguridad lo permite, la aplicación también puede causar su propia desaparición invocando el método exit() de la clase Runtime o System.

La jerarquía de llamadas no se rige por usted sino que se rige por el planificador de subprocesos subyacente.

Así por ejemplo, si se me acaba el mismo código en mi máquina esta es la salida

Exception in thread "main" java.lang.RuntimeException: Exception from main thread 
    at TestThread.main(TestThread.java:6) 
Exception in thread "Thread-1" java.lang.RuntimeException: Exception from child thread 
    at TestThread.run(TestThread.java:9) 
    at java.lang.Thread.run(Thread.java:662) 

por lo que cuando se ejecutó tu ejemplo, planificador optan por dejar ir hilo hijo antes de principal.

Añadiendo a @JB Nizet, la forma en que se invocará un programa o cómo se implementará un ciclo de vida de hilo depende del sistema operativo y el hardware subyacentes, lo que varía y varía.

No hay detalles únicos de implementación que proporcionen una respuesta completa, cada implementación variará.

+1

lea la actualización – mprabhat

+0

que para explica los hilos daemon y la terminación del hilo. No es mi pregunta. >> "es un procedimiento estándar" ¿Cómo se implementa el procedimiento estándar? –

+0

La JVM realiza la implementación en sí. No puedes duplicarlo ni nada, es solo "magia". –

7

Si el método main() se inicia a través de un hilo, ¿por qué does not run() aparece en la parte superior de la jerarquía de invocación?

Como han mencionado otros, esto se debe a que el hilo "principal" es especial. No se inicia a través de los mecanismos de clase estándar Thread sino a través del código de arranque de Java. El public static void main(String[] args) siempre se ejecuta con el hilo principal desde el código nativo.

Otra explicación es que realmente existe un método run(), pero la forma en que construyen el bastidor se lo oculta a propósito con el fin de no confundir al usuario. Por ejemplo, como está haciendo un new Thread(new Test()), su clase Test es en realidad el campo target dentro del Thread. Cuando se pone en marcha el fondo Thread los que en realidad llama Thread.run() que tiene el código:

public void run() { 
    if (target != null) { 
     target.run(); 
    } 
} 

Pero nunca ver el método Thread.run() en el entorno de pila aunque parece que debería estar allí. El método run()sería en el marco de la pila si el usuario lo anula en una superclase Thread. Podría ser eliminado por el JDK para mejorar la producción de fotogramas.

Multi-threading en Java se hace definiendo run() e invocando start().

Esto es correcto, pero para la posteridad pensé que era importante darse cuenta de que su código tiene un problema. Su clase Test debe no extenderse Thread sino que debe implementar Runnable. Funciona porque Thread implementa Runnable.

O se debe implementar Runnable y cambiar el código para algo como esto:

public class Test implements Runnable { 
    public static void main(String[] args) throws Exception { 
     new Thread(new Test()).start(); 
     throw new RuntimeException("Exception from main thread"); 
    } 
    public void run() { 
     throw new RuntimeException("Exception from child thread"); 
    } 
} 

O todavía se extenderá Thread y cambiar la forma de empezar su hilo a algo como lo siguiente. Se recomienda el patrón Runnable anterior, ya que permite que su subproceso Test amplíe otra clase si es necesario.

public class Test extends Thread { 
    public static void main(String[] args) throws Exception { 
     new Test().start(); 
     throw new RuntimeException("Exception from main thread"); 
    } 
    @Override 
    public void run() { 
     throw new RuntimeException("Exception from child thread"); 
    } 
} 

¿Por qué es esto importante? Su código actual es instantiates 2 objetos Thread pero solo uno de ellos es start() ed y se ejecuta como fondo Thread. Usted podría tener algo como el siguiente error:

public class Test extends Thread { 
    public static void main(String[] args) throws Exception { 
     Test test = new Test(); 
     new Thread(test).start(); 
     // this is not interrupting the background thread 
     test.interrupt(); 
0

tal vez es un argumento semántico, sino un hilo y un proceso no son sinónimos.

Un proceso es iniciado por el sistema operativo y tiene sus propias páginas de códigos privadas (conjunto de código compilado). Un subproceso se inicia desde el programa interno, y comparte inicialmente las páginas de códigos principales (conjunto compilado de código).

Que la JVM utiliza internamente un subproceso para ejecutar el método principal es un detalle de implementación del entorno, pero no una representación del lenguaje Java. Si un subproceso fuera a informar en los cuadros de pila main, la arquitectura de referirse a la posición del código fuente sería imposible, porque ese hilo de servicio principal no tendría unidad de compilación (es interno a la JVM).

Cuestiones relacionadas