2010-04-07 11 views
6

Ok, sé que las dos formas estándar para crear un nuevo hilo y ejecutarlo en Java:Java - Método de llamada al inicio en el hilo: ¿cómo se dirige a la ejecución de la interfaz de Runnable()?

  1. Implementar Runnable en una clase, defina run() método, y pasar una instancia de la clase a un nuevo Thread. Cuando se llama al método start() en la instancia de subproceso, se invoca el método de ejecución de la instancia de clase.

  2. Que la clase deriva de Thread, por lo que puede reemplazar el método run() y luego, cuando se llama al método de una nueva instancia start(), la llamada se encamina al método reemplazado.

En ambos métodos, básicamente, una nueva Thread objeto se crea y su método de inicio invocado. Sin embargo, mientras que en el segundo método, el mecanismo de la llamada que se enruta al método definido por el usuario run() es muy claro, (es un polimorfismo en tiempo de ejecución simple en juego), no entiendo cómo la llamada al método start() en el objeto Thread se enruta al método run() de la clase que implementa la interfaz Runnable. ¿La clase Thread tiene un campo privado de Tipo Runnable que comprueba primero y, si está configurada, invoca el método de ejecución si se establece en un objeto? ese sería un extraño mecanismo IMO.

¿Cómo se deriva la llamada a start() en un subproceso al método de ejecución de la interfaz Runnable implementada por la clase cuyo objeto se pasa como parámetro al construir el subproceso?

Respuesta

7

El Thread guarda una referencia a la instancia Runnable y lo llama en la implementación base de run.

Esto se puede ver en la fuente:

// passed into the constructor and set in the init() method 
private Runnable target; 
... 
// called from native thread code after start() is called 
public void run() { 
    if (target != null) { 
     target.run(); 
    } 
} 
+0

¿Presumiblemente esto a menudo será una referencia a 'este' como en el segundo método? – Finbarr

+0

Esto no responde a su pregunta. Si deriva de Thread, la referencia Runnable, llamada target en la fuente, es nula. –

+0

@Frederik: Sí, pero como eliminaste 'ejecutar', no le pasará nada. – SLaks

1

En los dos casos tiene que haber clase Thread concreto. En el primer caso (implementando un Runnable), hace que la clase que lo implementa sea capaz de 'ser' un hilo. Aún debe pasar su clase como argumento al constructor de la clase Thread. Mientras que ese no es el escenario en el segundo caso donde extiendes una clase de subprocesos.

Cuando se invoca un método start(), no hay garantía de que el método run() se invoque inmediatamente. Llamar a un método start() indica que el hilo está listo para ejecutarse. Puede ir a cualquiera de los estados a partir de entonces dependiendo del Pooler de subprocesos.

FYI: class Thread implements Runnable

1

Usted podría tener acaba de comprobar la fuente de Thread.java incluido como parte del JDK:

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

donde objetivo:

private Runnable target; 

Pero creo que la verdadera la respuesta que está buscando es detalles sobre cómo funcionan realmente los hilos. Desafortunadamente, eso se abstrajo en las bibliotecas nativas. Intente obtener un alto nivel de comprensión sobre cómo funciona el enhebrado.

2

Mientras que usted puede mirar el código fuente real, en un supongo que sería algo así como:

public class MyThread implements Runnable { 
private Runnable r; 
public MyThread() { 
} 
public MyThread(Runnable r) { 
     this.r = r; 
} 

public void start() { 
    //magic to launch a new thread 
    run(); // the above magic would probably call run(), rather than 
      // call it directly here though. 
    } 
    public void run() { 
    if(r != null) 
     r.run(); 
    } 
} 

En resumen, si se amplía MyThread y anular run(), el método de su ejecución() sería llamado. Si pasó un Runnable en su lugar, el método run() de MyThread simplemente delegaría al método run() de ese Runnable.

+0

tristemente * inserte magia aquí * es la explicación más simple – Pyrolistical

+1

Su suposición es completamente correcta, excepto que 'r' se llama' objetivo', y que el constructor llama a un método 'init' que lo establece. – SLaks

1

Lo que las respuestas aún no han explorado es cómo van las cosas desde start() hasta run(), que es a la vez simple y complejo.

En términos simplistas, el método start() llama a un método nativo (start0 en la implementación OpenJDK) que asigna algo de memoria para una nueva pila y le pide al sistema operativo para ejecutar un hilo con ese espacio tan pila y con un C llana función ++ (thread_entry en la implementación de OpenJDK) como función de implementación. Esa función a su vez devuelve el procesador a Java para llamar al método run() en el objeto Thread. El patrón en el nivel bajo (pidiendo al sistema operativo que inicie un nuevo hilo en una pila y con una función) debería ser familiar para cualquiera que realice subprocesos nativos en sistemas POSIX o Windows.

El detalle lo hace todo mucho más complejo, con todo el manejo de errores y cajas de bordes oscuros que deben manejarse. Si tiene curiosidad, lea las fuentes OpenJDK, preste especial atención a Thread.java, JVM_StartThread en jvm.cpp y la clase JavaThread en thread.cpp y thread.hpp. Esperemos que esta respuesta le proporcione suficientes detalles para que pueda encontrar su propio camino ...

Cuestiones relacionadas