¿Cuándo llamarías a thread.run () de java en lugar de thread.start ()?

109

¿Cuándo llamarías a Java en thread.run()lugar de thread.start()?

blanco
fuente
47
¿Cuándo soy el método thread.start ()? :)
Bill the Lizard
3
@blank, la respuesta es simple: t.run()cuando quiere ejecutar tla tarea en el hilo actual, y t.start()cuando quiere ejecutar tla tarea en el hilo tmismo. ¿O está preguntando por casos de uso reales?
Pacerier
2
¡Cuando eres un idiota y quieres pasar una hora depurando código multiproceso para darte cuenta más tarde de que deberías haber llamado start()! Como yo ... ¡Este método no debería ser público!
Pierre Henry

Respuestas:

113

Es posible que desee llamar a run () en una prueba unitaria particular que se refiera estrictamente a la funcionalidad y no a la concurrencia.

Paul Croarkin
fuente
95

Nunca. Llamar a run () directamente solo ejecuta el código sincrónicamente (en el mismo hilo), como una llamada a un método normal.

Adam Crume
fuente
25
"Nunca" es un poco demasiado absoluto. ¿Quizás no siempre quieres un nuevo hilo y aún así ejecutas el código?
Tomalak
4
Quizás, pero en ese caso sería innecesariamente un desperdicio crear un nuevo Thread solo para llamar al método run (). Es mejor crear un impl Runnable y ejecutar ese subproceso o construir e iniciar un nuevo subproceso con él.
Scott Bale
1
Solo volviendo a visitar ... si nunca, ¿por qué el método es público?
blanco
4
Es público porque Thread implementa Runnable. Puede subclasificar Thread y anular run (), que tiene el mismo efecto que poner su código en un Runnable y pasarlo al constructor de Thread. Sin embargo, es una mejor práctica usar un objeto Runnable separado, ya que eso te deja más flexibilidad (como pasarlo a un Ejecutor, etc.).
Adam Crume
2
Permítanme darles un ejemplo concreto con el que estoy trabajando actualmente: tengo un programa que se puede ejecutar como GUI o desde la línea de comandos. En el caso de la GUI, quiero que el objeto que hace el trabajo pesado se ejecute en un hilo separado y envíe actualizaciones a la interfaz gráfica de usuario. En el modo de línea de comando, no necesito ese hilo separado.
Edward Falk
27

Tomado de las preguntas frecuentes sobre hilos de Java de estilo de código :

P: ¿Cuál es la diferencia entre los métodos start () y run () de un hilo?

R: Los métodos separados start () y run () de la clase Thread proporcionan dos formas de crear programas con subprocesos. El método start () inicia la ejecución del nuevo hilo y llama al método run (). El método start () regresa inmediatamente y el nuevo hilo normalmente continúa hasta que regresa el método run ().

El método run () de la clase Thread no hace nada, por lo que las subclases deben anular el método con código para ejecutar en el segundo hilo. Si se crea una instancia de un hilo con un argumento Runnable, el método run () del hilo ejecuta el método run () del objeto Runnable en el nuevo hilo.

Dependiendo de la naturaleza de su programa enhebrado, llamar al método Thread run () directamente puede dar el mismo resultado que llamar a través del método start (), pero en el último caso, el código se ejecuta en un nuevo hilo.

Tomalak
fuente
thread's run() method executes the run() method of the Runnable object in the new thread instead.Eso no es cierto (o al menos mi código fuente de Java 8 dice lo contrario), pero desafortunadamente el enlace parece roto, así que informo el error aquí.
kajacx
1
@Tomalak, esto no responde a la pregunta formulada. La pregunta no es pedir la diferencia, sino preguntar sobre casos de uso en los que llamaremos en thread.run()lugar de thread.start().
Pacerier
24

La ejecución thread.run()no crea una nueva Threaden la que se ejecuta su código. Simplemente ejecuta el código en el Thread actual desde el que thread.run()se invoca el código.

La ejecución thread.start()crea un nuevo hilo de nivel de sistema operativo en el run()que se llama al método.

En esencia:

Programación de un solo hilo → Llamar directamente al run()método

Programación multiproceso → Llamar al start()método

Además, como han mencionado otros, "probar" parece ser el único caso aconsejable en el que puede invocar run()directamente desde su código.

Mahendra Liya
fuente
13

Ya se ha aludido a esto, pero para que quede claro: crear un nuevo objeto Thread solo para llamar a su método run () es innecesariamente caro y debería ser una señal de alerta importante. Sería un diseño mucho mejor y más desacoplado crear un impl Runnable y (a) llamar a su método run () directamente si ese es el comportamiento deseado, o (b) construir un nuevo Thread con ese Runnable e iniciar el Thread.

Mejor aún, para un desacoplamiento aún mayor, consulte la Executorinterfaz y el marco en JDK 5 y versiones posteriores. Esto le permite, en pocas palabras, desacoplar la ejecución de la tarea (la instancia Runnable) de cómo se ejecuta (la implementación Executor, que podría ejecutar el Runnable en el Thread actual, en un Thread nuevo, utilizando un Thread existente de un grupo, Y qué no).

Scott Bale
fuente
9

Llame thread.start(), a su vez llamará thread.run(). No puedo pensar en un caso en el que quiera omitir thread.start()e ir directamente athread.run()

Chris Ballance
fuente
3
Durante las pruebas es el único caso legítimo que se me ocurre. De lo contrario, el contenido de run () debería estar en un método separado al que se llama mediante run o por otros medios.
Bill the Lizard
9

Los métodos separados start()y run()de la clase Thread proporcionan dos formas de crear programas con subprocesos. El start()método inicia la ejecución del nuevo hilo y llama al run()método. El start()método regresa inmediatamente y el nuevo hilo normalmente continúa hasta run()que regresa el método.

El run()método de la clase Thread no hace nada, por lo que las subclases deben anular el método con código para ejecutar en el segundo hilo. Si se crea una instancia de un hilo con un argumento Runnable, el run()método del hilo ejecuta el run()método del objeto Runnable en el nuevo hilo.

Dependiendo de la naturaleza de su programa enhebrado, llamar al run()método Thread directamente puede dar el mismo resultado que llamar a través del start()método, pero en el último caso, el código se ejecuta en un nuevo hilo.

referencia

alok
fuente
Igual que la respuesta de Tomalak !! Si ha hecho referencia desde algún lugar, por favor mencione eso !!
Barry
The start() method returns immediately and the new thread normally continues until the run() method returns.Si start()regresa de inmediato, ¿cómo es que run()continúa ejecutándose dado que se llamó a sí mismo desdestart()
KNU
7

Si la pregunta era: "¿por qué se llama al método de inicio del hilo en lugar de ejecutar el método directamente?", Entonces he respondido con un código de ejemplo a continuación. Espero que aclare. En el ejemplo siguiente:

/*
By calling t1.start(), 
we are getting the main calling thread returned immediately 
after the t1.start() called and is ready to proceed for other 
operations.And the thread t1 starts executing the run method of the object r. 
Hence the the output will be:

      I am the main thread , i created thread t1 and had it execute run method, which is currently looping from 0 to 1000000

      I am done executing run method of testThread

*/


/* If we call t1.run() instead of t1.start(), (just replace t1.start() with t1.run() in the code for testing)
 its like a regular method call and the main thread will not return until the run method completes, 
 hence the output will be:

         I am done executing run method of testThread

         I am the main thread , i created thread t1 and had it execute run method, which is currently looping for i to 1000000

*/


class testThread implements Runnable{

 public void run()
 {
     for(int i=0;i<1000000;i++){} //a simple delay block to clarify.

     System.out.println("I am done executing run method of testThread");

 }  
}

public class mainClass{

   public static void main(String [] args)
    {
          testThread r = new testThread();
          Thread t1 = new Thread(r);
          t1.start();  /* Question is: can we call instead t1.run() */  
          System.out.println("I am the main thread , i created thread t1 and had it execute run method, which is currently looping for i to 1000000");

    }
}
Steer360
fuente
5

Cuando desee que se ejecute sincrónicamente. Llamar al método de ejecución en realidad no le dará múltiples subprocesos. El método de inicio crea un nuevo hilo que llama al método de ejecución.

Brian
fuente
3

Si desea ejecutar el contenido de run () como lo haría con cualquier otro método. No para iniciar un hilo, por supuesto.


fuente
3

Suponiendo que conoce el uso del método de inicio y ejecución, es decir, síncrono frente a asíncrono; El método de ejecución se puede utilizar solo para probar la funcionalidad.

Además, en algunas circunstancias, la misma clase de subproceso se puede usar en dos lugares diferentes con requisitos de funcionalidad de sincronización y asincronización al tener dos objetos diferentes con el método de ejecución de uno y el método de inicio de otro invocado.

Salman Kasbati
fuente
2

Al menos en la JVM 1.6., Hay un poco de verificación y la ejecución se llama de forma nativa:

 public synchronized void start() {
        /**
     * This method is not invoked for the main method thread or "system"
     * group threads created/set up by the VM. Any new functionality added 
     * to this method in the future may have to also be added to the VM.
     *
     * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();
        group.add(this);
        start0();
        if (stopBeforeStart) {
        stop0(throwableFromStop);
    }
    }

    private native void start0();
Steve B.
fuente
2

Solo una nota a los excelentes comentarios anteriores: a veces escribes un código de múltiples subprocesos que usa el método "start" para ejecutar diferentes subprocesos. Le resultará mucho más fácil si usa "ejecutar" (en lugar de "iniciar) para depurar, ya que hace que el código se ejecute sincrónicamente y depurarlo mucho más fácilmente.

msamadi
fuente
-1
public class TestClass implements Runnable {
    public static void main(String[] args) {
        TestClass tc = new TestClass();

        Thread t1 = new Thread(tc);
        System.out.println("Before Starting Thread " + Thread.currentThread().hashCode());
        t1.start();
        System.out.println("After Starting Thread " + Thread.currentThread().hashCode());
    }

    @Override
    public void run() {
        System.out.println("TestClass Run method is  Running with thread " + Thread.currentThread().hashCode());        
    }
}
Avatar Jirase
fuente
Hola Frnz, Echa un vistazo y ejecuta el ejemplo anterior para entender claramente, primero ejecuta con t1.start () y ver el código hash y la próxima vez con los códigos hash t1.run () y chk
Avatar Girase
¿Dónde está tu pregunta?
Amén Jlili