java - example - ¿Cuál es la diferencia entre Thread start() y Runnable run()?
thread java (14)
Digamos que tenemos estos dos Runnables:
class R1 implements Runnable {
public void run() { … }
…
}
class R2 implements Runnable {
public void run() { … }
…
}
Entonces, ¿cuál es la diferencia entre esto?
public static void main() {
R1 r1 = new R1();
R2 r2 = new R2();
r1.run();
r2.run();
}
Y esto:
public static void main() {
R1 r1 = new R1();
R2 r2 = new R2();
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
}
En el primer caso, simplemente está invocando el método run()
de los objetos r1
y r2
.
¡En el segundo caso estás creando 2 nuevos hilos!
start()
llamará run()
en algún momento!
En realidad, Thread.start()
crea un nuevo hilo y tiene su propio escenario de ejecución.
Thread.start()
llama al método run()
forma asíncrona, lo que cambia el estado del nuevo Thread a Runnable.
Pero Thread.run()
no crea ningún hilo nuevo. En su lugar, ejecuta el método de ejecución en el hilo en ejecución actual de forma síncrona.
Si está utilizando Thread.run()
entonces no está utilizando las funciones de subprocesos múltiples.
La diferencia es que cuando el programa start()
método start()
, se crea un nuevo hilo y el código dentro de run()
se ejecuta en el nuevo hilo, mientras que si llama directamente al método run()
no se creará un nuevo hilo y el código dentro de run()
Ejecutar en el hilo actual directamente.
Otra diferencia entre start()
y run()
en el subproceso de Java es que no se puede llamar a start()
dos veces. Una vez iniciada, la segunda llamada start()
lanzará la IllegalStateException
en Java, mientras que puede llamar al método run()
varias veces, ya que es solo un método ordinario .
La diferencia es que Thread.start()
inicia un subproceso que llama al método run()
, mientras que Runnable.run()
simplemente llama al método run()
en el subproceso actual.
La mayoría de estas respuestas pasan por alto el panorama general, que es que, en lo que respecta al lenguaje Java, no hay más diferencia entre t.start()
y r.run()
que entre los otros dos métodos.
Ambos son solo métodos. Ambos corren en el hilo que los llamó . Ambos hacen lo que fueron codificados para hacer, y luego ambos regresan, todavía en el mismo hilo, a sus interlocutores.
La mayor diferencia es que la mayoría del código para t.start()
es código nativo , mientras que, en la mayoría de los casos, el código para r.run()
será Java puro. Pero eso no es una gran diferencia. El código es el código. El código nativo es más difícil de encontrar y más difícil de entender cuando lo encuentras, pero aún así es solo un código que le dice a la computadora qué hacer.
Entonces, ¿qué hace t.start()
?
Crea un nuevo hilo nativo, organiza ese hilo para que llame a t.run()
y luego le dice al sistema operativo que permita que el nuevo hilo se ejecute. Entonces vuelve.
¿Y qué hace r.run()
?
Lo gracioso es que la persona que hace esta pregunta es la persona que la escribió . r.run()
hace lo que usted (es decir, el desarrollador que lo escribió) diseñó para hacerlo.
t.start()
es el método que la biblioteca proporciona para que su código llame cuando desee un nuevo hilo.
r.run()
es el método que proporciona para que la biblioteca llame al nuevo hilo.
Los métodos separados start () y run () en la clase Thread proporcionan dos formas de crear programas threaded. 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 el código que se ejecutará en el segundo hilo. Si un Thread se crea una instancia con un argumento Runnable, el método run () del thread ejecuta el método run () del objeto Runnable en el nuevo thread.
Dependiendo de la naturaleza de su programa de subprocesos, llamar al método Thread run () directamente puede dar el mismo resultado que llamar a través del método start (), pero en este último caso, el código se ejecuta realmente en un nuevo hilo.
Los puntos que hicieron los miembros están bien, así que solo quiero agregar algo. Lo que pasa es que JAVA no admite herencia múltiple. Pero ¿Qué sucede si desea derivar una clase B de otra clase A, pero solo puede derivar de una clase? El problema ahora es cómo "derivar" de ambas clases: A y Thread. Por lo tanto, puede utilizar la interfaz ejecutable.
public class ThreadTest{
public void method(){
Thread myThread = new Thread(new B());
myThread.start;
}
}
public class B extends A implements Runnable{...
Método de sobrescritura de ejecución del método Start () de la clase extendida Thread y la interfaz de implementables Runnable.
Pero al llamar a run (), busque el método de ejecución, pero si la clase implementa la interfaz Runnable, entonces invoca el método de ejecución runnable de (Runnable).
ex.:
`
public class Main1
{
A a=new A();
B b=new B();
a.run();//This call run() of Thread because run() of Thread only call when class
//implements with Runnable not when class extends Thread.
b.run();//This not run anything because no run method found in class B but it
//didn''t show any error.
a.start();//this call run() of Thread
b.start();//this call run() of Thread
}
class A implements Runnable{
@Override
public void run() {
System.out.println("A ");
}
}
class B extends Thread {
@Override
public void run() {
System.out.println("B ");
}
}
`
Si run()
en el método principal, el subproceso del método principal invocará el método de run
lugar del subproceso que necesita para ejecutar.
El método start()
crea un nuevo hilo y para el cual se debe run()
método run()
Si llama directamente al método run()
, no está utilizando la función de subprocesos múltiples ya que el método run()
se ejecuta como parte del subproceso de la persona que llama.
Si llama al método start()
en el subproceso, la máquina virtual Java llamará al método run () y dos subprocesos se ejecutarán simultáneamente: el subproceso actual ( main()
en su ejemplo) y el otro subproceso (Runnable r1
en su ejemplo).
Eche un vistazo al código fuente del método start()
en la clase Thread
/**
* Causes this thread to begin execution; the Java Virtual Machine
* calls the <code>run</code> method of this thread.
* <p>
* The result is that two threads are running concurrently: the
* current thread (which returns from the call to the
* <code>start</code> method) and the other thread (which executes its
* <code>run</code> method).
* <p>
* It is never legal to start a thread more than once.
* In particular, a thread may not be restarted once it has completed
* execution.
*
* @exception IllegalThreadStateException if the thread was already
* started.
* @see #run()
* @see #stop()
*/
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();
En el código anterior, no puede ver la invocación al método run()
.
private native void start0()
es responsable de llamar al método run()
. JVM ejecuta este método nativo.
Si simplemente invoca run()
directamente, se ejecuta en el subproceso de llamada, como cualquier otro método de llamada. Se requiere que Thread.start()
cree realmente un nuevo hilo para que el método de run
del ejecutable se ejecute en paralelo.
invoke run()
está ejecutando en el subproceso de llamada, como cualquier otra llamada de método. mientras que Thread.start()
crea un nuevo hilo. invocar run()
es un error programático.
Thread.start()
código Thread.start()
registra el subproceso con el programador y el programador llama al método run()
. Además, Thread
es clase mientras que Runnable
es una interfaz.
Primer ejemplo: No hay múltiples hilos. Ambos se ejecutan en hilo único (existente). Sin creación de hilos.
R1 r1 = new R1();
R2 r2 = new R2();
r1
y r2
son solo dos objetos diferentes de clases que implementan la interfaz Runnable
y, por lo tanto, implementan el método run()
. Cuando llamas a r1.run()
lo estás ejecutando en el hilo actual.
Segundo ejemplo: dos hilos separados.
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1
y t2
son objetos de la clase Thread
. Cuando llama a t1.start()
, comienza un nuevo hilo y llama al método run()
de r1
internamente para ejecutarlo dentro de ese nuevo hilo.