"Implementa Runnable" vs "Extend Thread" en Java

Desde el tiempo que he pasado con subprocesos en Java, he encontrado estas dos formas de escribir subprocesos:

Con implements Runnable:

public class MyRunnable implements Runnable {
    public void run() {
        //Code
    }
}
//Started with a "new Thread(new MyRunnable()).start()" call

O con extends Thread:

public class MyThread extends Thread {
    public MyThread() {
        super("MyThread");
    }
    public void run() {
        //Code
    }
}
//Started with a "new MyThread().start()" call

¿Existe alguna diferencia significativa en estos dos bloques de código?

preguntado el 12 de febrero de 09 a las 12:02

Gracias por esta pregunta, las respuestas aclararon muchos conceptos erróneos que tenía. Busqué la forma correcta de hacer subprocesos de Java antes de que existiera SO y había mucha información errónea / información desactualizada. -

hay una razón por la que es posible que desee extender Thread (pero no lo recomiendo), puede manejar de forma preventiva interrupt(). Nuevamente, es una idea, podría ser útil en el caso correcto, sin embargo no la recomiendo. -

Consulte también la respuesta, bien explicada: stackoverflow.com/q/5562720/285594 -

@bestsss, estoy tratando de descifrar a qué te refieres con el manejo de interrupt (). ¿Estás intentando anular el método? -

si Según el código, la clase Thread A puede extender cualquier clase, mientras que la clase Thread B no puede extender ninguna otra clase -

30 Respuestas

Si: implementos Runnable es la forma preferida de hacerlo, en mi opinión. Realmente no estás especializando el comportamiento del hilo. Solo le estás dando algo para que corra. Eso significa composición es la filosóficamente "más pura" forma de hacerlo.

In práctico términos, significa que puede implementar Runnable y extenderse desde otra clase también ... y también puede implementar Runnable a través de una expresión lambda a partir de Java 8.

Respondido 26 Oct 20, 14:10

Exactamente, bien dicho. ¿Qué comportamiento estamos tratando de sobrescribir en Thread extendiéndolo? Yo diría que la mayoría de la gente no intenta sobrescribir ningún comportamiento, sino que intenta utilizar el comportamiento de Thread. - anzuelo

Como comentario lateral, si crea una instancia de un Thread y no llama a su método start (), está creando una pérdida de memoria en Java <5 (esto no sucede con Runnables): stackoverflow.com/questions/107823/… - Nacho coloma

Una ventaja menor de Runnable es que, si en ciertas circunstancias no le importa, o no quiere usar el subproceso, y solo quiere ejecutar el código, tiene la opción de simplemente llamar a run (). p. ej. (muy ondulado a mano) if (numberCores > 4) myExecutor.excute(myRunnable); else myRunnable.run() - user949300

@ user949300 también puedes hacer eso con extends Thread y si no quiere enhebrar, ¿por qué implementaría Runnable... - m0skit0

Parafraseando a Sierra y Bates, un beneficio clave de implementar Runnable es que estás separando arquitectónicamente el "trabajo" del "corredor". - 8bitjunkie

tl; dr: implements Runnable es mejor. Sin embargo, la advertencia es importante

En general, recomendaría usar algo como Runnable más bien que Thread porque le permite mantener su trabajo solo vagamente junto con su elección de concurrencia. Por ejemplo, si usa un Runnable y decidir más adelante que esto, de hecho, no requiere su propio Thread, puede llamar a threadA.run ().

Advertencia: Por aquí, desaconsejo encarecidamente el uso de hilos sin procesar. Prefiero mucho el uso de Llamables y Futuras Tareas (Del javadoc: "Un cálculo asincrónico cancelable"). La integración de tiempos de espera, la cancelación adecuada y la agrupación de subprocesos del soporte de concurrencia moderno son mucho más útiles para mí que las pilas de subprocesos sin procesar.

Seguir: hay un FutureTask constructor que le permite usar Runnables (si eso es con lo que se siente más cómodo) y aún así obtener el beneficio de las herramientas de concurrencia modernas. Para citar el javadoc:

Si no necesita un resultado en particular, considere usar construcciones de la forma:

Future<?> f = new FutureTask<Object>(runnable, null)

Entonces, si reemplazamos sus runnable con tu threadA, obtenemos lo siguiente:

new FutureTask<Object>(threadA, null)

Otra opción que te permite estar más cerca de Runnables es un ThreadPoolExecutor. Puedes usar el ejecutar método para pasar un Runnable para ejecutar "la tarea dada en algún momento en el futuro".

Si desea intentar usar un grupo de subprocesos, el fragmento de código anterior se convertiría en algo como lo siguiente (usando el Executors.newCachedThreadPool () método de fábrica):

ExecutorService es = Executors.newCachedThreadPool();
es.execute(new ThreadA());

Respondido 14 ago 19, 13:08

Esto es mejor que la respuesta aceptada en mi humilde opinión. Una cosa: el fragmento de código que tiene no cierra el ejecutor y veo millones de preguntas en las que las personas se equivocan, creando un nuevo Ejecutor cada vez que quieren generar una tarea. es sería mejor como campo estático (o inyectado), por lo que solo se crea una vez. - Artbristol

@artbristol, ¡gracias! No estoy en desacuerdo con el nuevo Ejecutor (hacemos lo que sugieres en nuestro código). Al escribir la respuesta original, estaba tratando de escribir un código mínimo análogo al fragmento original. Tenemos que esperar que muchos lectores de estas respuestas las utilicen como puntos de partida. No estoy tratando de escribir un reemplazo para el javadoc. Estoy escribiendo material de marketing para ello: Si te gusta este método, ¡deberías ver todas las otras cosas geniales que tenemos para ofrecer ...! - Bob Cross

Sé que estoy un poco tarde para comentar esto, pero lidiando con FutureTask directamente no es generalmente lo que quieres hacer. ExecutorServices creará el apropiado Future para ti cuando tu submit a Runnable/Callable a ellos. Lo mismo para ScheduledExecutorServices y ScheduledFuture cuando tú schedule a Runnable/Callable. - Señor de poder

@Powerlord, mi intención era hacer fragmentos de código que coincidieran con los OP lo más cerca posible. Estoy de acuerdo en que la nueva FutureTask no es óptima, pero está claro a los efectos de la explicación. - Bob Cross

Moraleja de la historia:

Herede solo si desea anular algún comportamiento.

O más bien debería leerse como:

Heredar menos, interactuar más.

Respondido 28 ago 15, 17:08

¡Esta debería ser siempre la pregunta si comienza a crear un objeto en ejecución simultánea! ¿Incluso necesita las funciones de Thread Object? - Libertée

Al heredar de Thread, casi siempre se quiere anular el comportamiento del run() método. - Warren rocío

No puede anular el comportamiento de un java.lang.Thread anulando el run() método. En ese caso, debe anular el start() método, supongo. Normalmente, solo reutiliza el comportamiento del java.lang.Thread inyectando su bloque de ejecución en el run() método. - sura2k

La herencia no es solo para anular algún comportamiento, también es para usar comportamientos comunes. Y es al contrario, cuanto más anula, peor jerarquía. - peja

Bueno, tantas buenas respuestas, quiero agregar más sobre esto. Esto ayudará a comprender Extending v/s Implementing Thread.
Extends vincula dos archivos de clase muy de cerca y puede causar que algunos sean bastante difíciles de manejar.

Ambos enfoques hacen el mismo trabajo, pero ha habido algunas diferencias.
La diferencia más común es

  1. Cuando extiende la clase Thread, después de eso, no puede extender ninguna otra clase que necesite. (Como sabes, Java no permite heredar más de una clase).
  2. Cuando implementa Runnable, puede ahorrar espacio para que su clase extienda cualquier otra clase en el futuro o ahora.

Sin embargo, uno diferencia significativa entre implementar Runnable y extender Thread es que
by extending Thread, each of your threads has a unique object associated with it, whereas implementing Runnable, many threads can share the same object instance.

El siguiente ejemplo le ayudará a comprender con mayor claridad

//Implement Runnable Interface...
class ImplementsRunnable implements Runnable {

    private int counter = 0;

    public void run() {
        counter++;
        System.out.println("ImplementsRunnable : Counter : " + counter);
    }
}

//Extend Thread class...
class ExtendsThread extends Thread {

    private int counter = 0;

    public void run() {
        counter++;
        System.out.println("ExtendsThread : Counter : " + counter);
    }
}
    
//Use the above classes here in main to understand the differences more clearly...
public class ThreadVsRunnable {

    public static void main(String args[]) throws Exception {
        // Multiple threads share the same object.
        ImplementsRunnable rc = new ImplementsRunnable();
        Thread t1 = new Thread(rc);
        t1.start();
        Thread.sleep(1000); // Waiting for 1 second before starting next thread
        Thread t2 = new Thread(rc);
        t2.start();
        Thread.sleep(1000); // Waiting for 1 second before starting next thread
        Thread t3 = new Thread(rc);
        t3.start();

        // Creating new instance for every thread access.
        ExtendsThread tc1 = new ExtendsThread();
        tc1.start();
        Thread.sleep(1000); // Waiting for 1 second before starting next thread
        ExtendsThread tc2 = new ExtendsThread();
        tc2.start();
        Thread.sleep(1000); // Waiting for 1 second before starting next thread
        ExtendsThread tc3 = new ExtendsThread();
        tc3.start();
    }
}

Salida del programa anterior.

ImplementsRunnable : Counter : 1
ImplementsRunnable : Counter : 2
ImplementsRunnable : Counter : 3
ExtendsThread : Counter : 1
ExtendsThread : Counter : 1
ExtendsThread : Counter : 1

En el enfoque de la interfaz Runnable, solo se está creando una instancia de una clase y ha sido compartida por diferentes subprocesos. Por lo tanto, el valor del contador se incrementa para todos y cada uno de los accesos a subprocesos.

Considerando que, en el enfoque de la clase Thread, debe tener que crear una instancia separada para cada acceso de subproceso. Por lo tanto, se asigna memoria diferente para cada instancia de clase y cada una tiene un contador separado, el valor sigue siendo el mismo, lo que significa que no se producirá ningún incremento porque ninguna de las referencias de objeto es la misma.

¿Cuándo usar Runnable?
Utilice la interfaz Runnable cuando desee acceder a los mismos recursos del grupo de subprocesos. Evite usar la clase Thread aquí, porque la creación de varios objetos consume más memoria y se convierte en una gran sobrecarga de rendimiento.

Una clase que implementa Runnable no es un hilo sino solo una clase. Para que un Runnable se convierta en un Thread, debes crear una instancia de Thread y pasar a sí mismo como objetivo.

En la mayoría de los casos, la interfaz Runnable debe usarse si solo planea anular la run() método y ningún otro método de Thread. Esto es importante porque las clases no deben subclasificarse a menos que el programador tenga la intención de modificar o mejorar el comportamiento fundamental de la clase.

Cuando existe la necesidad de extender una superclase, implementar la interfaz Runnable es más apropiado que usar la clase Thread. Porque podemos extender otra clase mientras implementamos la interfaz Runnable para hacer un hilo.

¡Espero que esto sea de ayuda!

Respondido 06 Jul 20, 22:07

Tu código es evidentemente incorrecto. Quiero decir, hace lo que hace, pero no lo que pretendías mostrar. - cero

Para aclarar: para el caso ejecutable, ha utilizado la misma instancia ImplementsRunnable para iniciar varios subprocesos, mientras que para el caso Thread está creando diferentes instancias ExtendsThread que obviamente conduce al comportamiento que mostró. La segunda mitad de su método principal debería ser: ExtendsThread et = new ExtendsThread(); Thread tc1 = new Thread(et); tc1.start(); Thread.sleep(1000); Thread tc2 = new Thread(et); tc2.start(); Thread.sleep(1000); Thread tc3 = new Thread(et); tc3.start(); ¿Está más claro? - cero

Todavía no entiendo su intención, pero mi punto es que si crea varias instancias de ExtendsThread, todas devolverán 1 (como ha mostrado). Puede obtener los mismos resultados para Runnable haciendo lo mismo allí, es decir, creando múltiples instancias de ImplementsRunnable. - cero

@zEro Hola, soy del futuro. Dado que su versión del código tiene Thread incrementándose también, es la declaración by extending Thread, each of your threads has a unique object associated with it, whereas implementing Runnable, many threads can share the same object instance entonces mal? Si no es así, ¿qué caso demuestra esto? - Lavadora malvada

@EvilWashingMachine: He estado inactivo durante mucho tiempo ... y acabo de ver esto. Agregué el código hash del objeto a las declaraciones de impresión ... + " hashcode: " + this.hashCode() - cero

Una cosa que me sorprende que aún no se haya mencionado es que implementar Runnable hace que tu clase sea más flexible.

Si extiende el hilo, la acción que está haciendo siempre estará en un hilo. Sin embargo, si implementa Runnable no tiene por qué serlo. Puede ejecutarlo en un subproceso o pasarlo a algún tipo de servicio ejecutor, o simplemente pasarlo como una tarea dentro de una aplicación de un solo subproceso (tal vez para ejecutarse en un momento posterior, pero dentro del mismo subproceso). Las opciones son mucho más abiertas si solo usa Runnable que si te unes a Thread.

Respondido 12 Oct 16, 13:10

Bueno, puedes hacer lo mismo con un Thread objeto también porque Thread implements Runnable… ;-) Pero "se siente mejor" haciendo estas cosas con un Runnable que hacerlos con un Thread! - siegi

Cierto, pero Thread agrega muchas cosas adicionales que no necesita y, en muchos casos, no desea. Siempre es mejor implementar la interfaz que coincida con lo que está haciendo en realidad. - Hermes

Si desea implementar o extender cualquier otra clase, entonces Runnable La interfaz es más preferible, de lo contrario, si no desea que ninguna otra clase se extienda o implemente, entonces Thread la clase es preferible.

La diferencia más común es

enter image description here

Cuando extends Thread class, después de eso no puede extender ninguna otra clase que requiera. (Como sabes, Java no permite heredar más de una clase).

Cuando implements Runnable, puede ahorrar espacio para que su clase amplíe cualquier otra clase en el futuro o ahora.

  • Java no admite herencias múltiples, lo que significa que solo puede extender una clase en Java, por lo que una vez que extendió la clase Thread, perdió su oportunidad y no puede extender o heredar otra clase en Java.

  • En la programación orientada a objetos, extender una clase generalmente significa agregar nueva funcionalidad y modificar o mejorar comportamientos. Si no estamos haciendo ninguna modificación en Thread, use la interfaz Runnable en su lugar.

  • La interfaz ejecutable representa una tarea que puede ser ejecutada por un subproceso simple o ejecutores o por cualquier otro medio. Por lo tanto, la separación lógica de Task como Runnable que Thread es una buena decisión de diseño.

  • Separar la tarea como Ejecutable significa que podemos reutilizar la tarea y también tenemos la libertad de ejecutarla desde diferentes medios. ya que no puede reiniciar un hilo una vez que se completa. nuevamente Runnable vs Thread para la tarea, Runnable es el ganador.

  • El diseñador de Java reconoce esto y es por eso que los Ejecutores aceptan Runnable como Tarea y tienen un hilo de trabajo que ejecuta esas tareas.

  • La herencia de todos los métodos de Thread es una sobrecarga adicional solo para representar una tarea que se puede hacer fácilmente con Runnable.

Cortesía de javarevisited.blogspot.com

Estas fueron algunas de las diferencias notables entre Thread y Runnable en Java. Si conoce alguna otra diferencia entre Thread y Runnable, compártala a través de los comentarios. Yo personalmente uso Runnable over Thread para este escenario y recomiendo usar la interfaz Runnable o Callable según sus requisitos.

Sin embargo, la diferencia significativa es.

Cuando extends Thread class, cada uno de sus hilos crea un objeto único y se asocia con él. Cuando usted implements Runnable, comparte el mismo objeto con varios subprocesos.

Respondido 22 Abr '19, 23:04

En realidad, no es prudente comparar Runnable y Thread juntos.

Estos dos tienen una dependencia y una relación en subprocesos múltiples al igual que Wheel and Engine relación de vehículo de motor.

Yo diría que solo hay una forma de subprocesos múltiples con dos pasos. Déjame hacer mi punto.

Ejecutable:
Al implementar interface Runnable significa que estás creando algo que es run able en un hilo diferente. Ahora crear algo que pueda ejecutarse dentro de un hilo (ejecutable dentro de un hilo), no significa crear un hilo.
Entonces la clase MyRunnable no es más que una clase ordinaria con un void run método. Y sus objetos serán algunos objetos ordinarios con solo un método run que se ejecutará normalmente cuando se llame. (a menos que pasemos el objeto en un hilo).

Hilo:
class Thread, Yo diría que una clase muy especial con la capacidad de iniciar un nuevo subproceso que en realidad permite múltiples subprocesos a través de su start() método.

¿Por qué no es prudente comparar?
Porque los necesitamos a ambos para subprocesos múltiples.

Para Multi-Threading necesitamos dos cosas:

  • Algo que se puede ejecutar dentro de un hilo (ejecutable).
  • Algo que puede iniciar un nuevo hilo (hilo).

Entonces, técnica y teóricamente, ambos son necesarios para iniciar un hilo, uno corrida y uno lo hará hazlo correr (Me gusta Wheel and Engine de vehículo de motor).

Es por eso que no puedes iniciar un hilo con MyRunnable necesitas pasarlo a una instancia de Thread.

Pero es posible crear y ejecutar un hilo solo usando class Thread porque clase Thread implementos Runnable para que todos sepamos Thread también es un Runnable interior.

Finalmente Thread y Runnable son complementarios entre sí para multiprocesos, no competidores ni reemplazos.

Respondido 03 ago 16, 06:08

¡Exactamente! Esta debería ser la respuesta aceptada. Por cierto, creo que la pregunta ha sido editada y ThreadA ya no tiene sentido - idelvall

la respuesta aceptada es mucho más delegado gracias por tu respuesta @idelvall - Saif

¡La mejor respuesta! ¡Gracias! - miguelye

Debe implementar Runnable, pero si está ejecutando Java 5 o superior, no debe iniciarlo con new Thread pero usa un EjecutorService en lugar de. Para obtener más detalles, consulte: Cómo implementar subprocesos simples en Java.

contestado el 23 de mayo de 17 a las 13:05

No creo que ExecutorService sea tan útil si solo desea iniciar un solo hilo. - Señor de poder

Por lo que he aprendido, uno ya no debería iniciar un hilo por su cuenta en general, porque dejar eso al servicio ejecutor hace que todo sea mucho más controlable (como, esperar a que el hilo se suspenda). Además, no veo nada en la pregunta que implique que se trata de un solo hilo. - Fabián Steeg

¿Cuál es el punto de usar cualquier subproceso múltiple si sabemos antes que va a ser un solo subproceso? Así que supongamos que tenemos varios hilos y esta respuesta es valiosa. - cero

@zEro Estoy bastante seguro de que hay una razón por la que solo hay un hilo de envío de eventos. Dudo que sea el único caso en el que sea mejor tener un hilo separado, pero posiblemente no sea mejor tener varios. - porcoesfino

No soy un experto, pero puedo pensar en una razón para implementar Runnable en lugar de extender Thread: Java solo admite herencia única, por lo que solo puede extender una clase.

Editar: Esto originalmente decía "Implementar una interfaz requiere menos recursos". también, pero necesita crear una nueva instancia de Thread de cualquier manera, por lo que esto estaba mal.

Respondido 12 Feb 09, 14:02

En Runnable no podemos hacer llamadas de red, ¿verdad? Como tengo android.os.NetworkOnMainThreadException. Pero al usar hilo puedo hacer llamadas de red. Por favor, corríjame si estoy equivocado. - nabeel thobani

@NabeelThobani Normal A Java no le importa, pero parece que sí lo hace Android. Sin embargo, no estoy lo suficientemente familiarizado con Android para decirlo. - Señor de poder

@NabeelThobani Por supuesto que puedes. Probablemente no esté creando un hilo con su Runnable. - m0skit0

Yo diría que hay una tercera forma:

public class Something {

    public void justAnotherMethod() { ... }

}

new Thread(new Runnable() {
   public void run() {
    instanceOfSomething.justAnotherMethod();
   }
}).start();

Tal vez esto esté un poco influenciado por mi reciente uso intensivo de Javascript y Actionscript 3, pero de esta manera su clase no necesita implementar una interfaz bastante vaga como Runnable.

Respondido 25 Oct 10, 22:10

Esta no es realmente una tercera vía. Todavía estás implementando Runnable, simplemente de forma anónima. - don roberto

@Don Roby: Que es diferente. A menudo es conveniente y puede usar campos y variables locales finales de la clase / método que los contiene. - Bart van Heukelom

@BartvanHeukelom Es conveniente, pero no diferente. Puede hacer esto con cualquier tipo de clase anidada, es decir, clases internas, clases locales y expresiones lambda. - xehpuk

Con el lanzamiento de Java 8, ahora hay una tercera opción.

Runnable es un interfaz funcional, lo que significa que se pueden crear instancias con expresiones lambda o referencias a métodos.

Su ejemplo puede reemplazarse con:

new Thread(() -> { /* Code here */ }).start()

o si quieres usar un ExecutorService y una referencia de método:

executor.execute(runner::run)

Estos no solo son mucho más cortos que sus ejemplos, sino que también vienen con muchas de las ventajas indicadas en otras respuestas de usar Runnable encima Thread, como la responsabilidad única y el uso de la composición porque no está especializando el comportamiento del hilo. De esta manera también evita crear una clase extra si todo lo que necesita es una Runnable como lo hace en sus ejemplos.

Respondido el 05 de Septiembre de 15 a las 13:09

Esta respuesta necesita explicación. Después de un poco de desconcierto, llego a la conclusión de que () -> {} se supone que representa la lógica personalizada que alguien necesita? Así que sería mejor decirlo como () -> { /* Code here */ }? - Fabricante de herramientasSteve

La creación de instancias de una interfaz brinda una separación más clara entre su código y la implementación de subprocesos, por lo que preferiría implementar Runnable en este caso.

Respondido 12 Feb 09, 14:02

Todos aquí parecen pensar que implementar Runnable es el camino a seguir y realmente no estoy en desacuerdo con ellos, pero también hay un caso para extender Thread en mi opinión, de hecho, lo has demostrado en tu código.

Si implementa Runnable, la clase que implementa Runnable no tiene control sobre el nombre del hilo, es el código de llamada el que puede establecer el nombre del hilo, así:

new Thread(myRunnable,"WhateverNameiFeelLike");

pero si extiende Thread, puede administrar esto dentro de la propia clase (al igual que en su ejemplo, nombra el hilo 'ThreadB'). En este caso usted:

A) podría darle un nombre más útil para fines de depuración

B) están obligando a que ese nombre se use para todas las instancias de esa clase (a menos que ignore el hecho de que es un hilo y haga lo anterior con él como si fuera un Runnable pero estamos hablando de una convención aquí en cualquier caso, por lo que puede ignorar esa posibilidad que siento).

Incluso podría, por ejemplo, tomar un seguimiento de la pila de su creación y usarlo como nombre del hilo. Esto puede parecer extraño, pero dependiendo de cómo esté estructurado su código, puede ser muy útil para fines de depuración.

Esto puede parecer una cosa pequeña, pero en la que tiene una aplicación muy compleja con muchos subprocesos y, de repente, las cosas 'se han detenido' (ya sea por razones de bloqueo o posiblemente debido a una falla en un protocolo de red que sería menos obvias, u otras razones interminables), luego obtener un volcado de pila de Java donde todos los subprocesos se llaman 'Thread-1', 'Thread-2', 'Thread-3' no siempre es muy útil (depende de cómo sean sus subprocesos estructurado y si puede saber cuál es cuál solo por su seguimiento de pila (no siempre es posible si está utilizando grupos de varios subprocesos que ejecutan el mismo código).

Habiendo dicho eso, por supuesto, también podría hacer lo anterior de una manera genérica creando una extensión de la clase de hilo que establece su nombre en un seguimiento de pila de su llamada de creación y luego usar eso con sus implementaciones Runnable en lugar de la clase estándar de Java Thread (ver más abajo) pero además del seguimiento de la pila, podría haber más información específica del contexto que sería útil en el nombre del hilo para la depuración (una referencia a una de las muchas colas o sockets que podría procesar, por ejemplo, en cuyo caso podría preferir extienda Thread específicamente para ese caso para que pueda hacer que el compilador lo obligue a usted (u otros que usen sus bibliotecas) a pasar cierta información (por ejemplo, la cola / socket en cuestión) para usar en el nombre).

Aquí hay un ejemplo del hilo genérico con el seguimiento de la pila de llamadas como su nombre:

public class DebuggableThread extends Thread {
    private static String getStackTrace(String name) {
        Throwable t= new Throwable("DebuggableThread-"+name);
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        PrintStream ps = new PrintStream(os);
        t.printStackTrace(ps);
        return os.toString();
    }

    public DebuggableThread(String name) {
        super(getStackTrace(name));
    }

    public static void main(String[] args) throws Exception {
        System.out.println(new Thread());
        System.out.println(new DebuggableThread("MainTest"));
    }
}

y aquí hay una muestra de la salida que compara los dos nombres:

Thread[Thread-1,5,main]
Thread[java.lang.Throwable: DebuggableThread-MainTest
    at DebuggableThread.getStackTrace(DebuggableThread.java:6)
    at DebuggableThread.<init>(DebuggableThread.java:14)
    at DebuggableThread.main(DebuggableThread.java:19)
,5,main]

Respondido el 20 de junio de 12 a las 00:06

cHao, ¿cuál es tu punto? No podría usar su código anterior durante la ejecución del hilo para obtener un seguimiento de la pila de la creación de los hilos (en su lugar, obtendría un nombre simple o, en el mejor de los casos, un seguimiento de la pila del lanzamiento de los hilos) pero subclasificando el hilo puede hacer exactamente eso y forzar incluso requiere más información específica del contexto, lo que le brinda una comprensión más concreta de exactamente qué hilo puede estar teniendo un problema. - Antónimo

Mi punto es que "Si implementa Runnable, la clase que implementa Runnable no tiene control sobre el nombre del hilo ..." es evidentemente falso. Una clase implementando Runnable De hecho, puede controlar el nombre del hilo, ya que el hilo que ejecuta el código es, por definición, el hilo actual (y cualquier código que pase los controles de seguridad tiene control sobre los nombres de los hilos). Teniendo en cuenta que dedica la mitad de su publicación a "Dios mío, ¿qué pasa con los nombres de los hilos?", Eso parece un poco importante. - chao

¿El nombre del hilo? Nada le impide extender la clase de hilo también. - RichieHH

Las diferencias entre extender subprocesos e implementar ejecutables son:

enter image description here

Respondido 01 Oct 17, 16:10

Ejecutable porque:

  • Deja más flexibilidad para la implementación Runnable para extender otra clase
  • Separa el código de la ejecución
  • Le permite ejecutar su ejecutable desde un grupo de subprocesos, el subproceso de eventos o de cualquier otra manera en el futuro.

Incluso si no necesita nada de esto ahora, es posible que lo necesite en el futuro. Dado que no hay ningún beneficio para anular Thread, Runnable es una mejor solución.

contestado el 07 de mayo de 10 a las 05:05

Dado que este es un tema muy popular y las buenas respuestas están repartidas por todas partes y tratadas con gran profundidad, sentí que era justificable compilar las buenas respuestas de los demás en una forma más concisa, para que los recién llegados tengan una descripción general sencilla por adelantado:

  1. Por lo general, extiendes una clase para agregar o modificar funciones. Entonces, si no quieres a exagerar cualquier Comportamiento del hilo, luego use Runnable.

  2. En la misma luz, si no lo necesitas a heredar métodos de hilo, puedes prescindir de eso gastos generales mediante el uso de Runnable.

  3. Herencia individual: Si extiende Thread, no puede extenderlo desde ninguna otra clase, por lo que si eso es lo que necesita hacer, debe usar Runnable.

  4. Es un buen diseño separar la lógica del dominio de los medios técnicos, en ese sentido es mejor tener una tarea ejecutable aislando tu tarea de tu corredor.

  5. Puede ejecutar el mismo Runnable objeto varias veces, un objeto Thread, sin embargo, solo se puede iniciar una vez. (Quizás la razón por la que los Ejecutores aceptan Runnables, pero no Threads).

  6. Si desarrolla su tarea como Ejecutable, tiene toda la flexibilidad cómo usarlo ahora y en el futuro. Puede hacer que se ejecute simultáneamente a través de Executors pero también a través de Thread. Y aún puede usar / llamarlo de manera no concurrente dentro del mismo hilo como cualquier otro tipo / objeto ordinario.

  7. Esto también hace que sea más fácil separado lógica de tareas y concurrencia aspectos en tu pruebas unitarias.

  8. Si está interesado en esta pregunta, también puede estar interesado en el diferencia entre invocable y ejecutable.

contestado el 23 de mayo de 17 a las 13:05

@Pino Sí, Thread en sí mismo también es Runnable. Sin embargo, si lo amplía para usarlo como Runnable, ¿cuál es el punto? ¿Por qué no usar un Runnable sencillo sin todo el equipaje? Entonces, diría que si extiende Thread, también lo ejecutaría usando su método de inicio, que solo se puede usar una vez. Ese es el punto que Nidhish-Krishnan quería hacer en su respuesta. Tenga en cuenta que el mío es solo una compilación o un breve resumen de otras respuestas aquí. - Jörg

Esto se discute en Oracle's Definición e inicio de un hilo tutorial:

¿Cuál de estos modismos debería utilizar? El primer idioma, que emplea un objeto Runnable, es más general, porque el objeto Runnable puede subclasificar una clase distinta de Thread. El segundo idioma es más fácil de usar en aplicaciones simples, pero está limitado por el hecho de que su clase de tarea debe ser descendiente de Thread. Esta lección se centra en el primer enfoque, que separa la tarea ejecutable del objeto Thread que ejecuta la tarea. Este enfoque no solo es más flexible, sino que también es aplicable a las API de administración de subprocesos de alto nivel que se tratan más adelante.

En otras palabras, implementar Runnable funcionará en escenarios donde su clase extiende una clase que no sea Thread. Java no admite herencia múltiple. Además, extendiendo Thread no será posible cuando se utilizan algunas de las API de administración de subprocesos de alto nivel. El único escenario donde se extiende Thread Es preferible que esté en una aplicación pequeña que no estará sujeta a actualizaciones en el futuro. Casi siempre es mejor implementar Runnable ya que es más flexible a medida que crece su proyecto. Un cambio de diseño no tendrá un impacto importante, ya que puede implementar muchas interfaces en Java, pero solo extender una clase.

Respondido el 21 de enero de 14 a las 16:01

La explicación más simple sería implementar Runnable podemos asignar el mismo objeto a varios subprocesos y cada uno Thread comparte los mismos estados de objeto y comportamiento.

Por ejemplo, suponga que hay dos subprocesos, thread1 pone un número entero en una matriz y thread2 toma enteros de la matriz cuando la matriz está llena. Tenga en cuenta que para thread2 para trabajar necesita saber el estado de la matriz, ya sea thread1 lo ha llenado o no.

Poner en marcha Runnable le permite tener esta flexibilidad para compartir el objeto mientras que extends Thread te hace crear nuevos objetos para cada hilo, por lo tanto, cualquier actualización realizada por thread1 se pierde en thread2.

Respondido el 03 de enero de 19 a las 07:01

Si no me equivoco, es más o menos parecido a

¿Cuál es la diferencia entre una interfaz y una clase abstracta?

extiende establece "Es un"relación e interfaz proporciona"Tiene un"capacidad.

Preferir implementa Runnable :

  1. Si no tiene que extender la clase Thread y modificar la implementación predeterminada de la API de Thread
  2. Si estás ejecutando un incendio y olvidas el comando
  3. Si ya está ampliando otra clase

Preferir "extiende el hilo"

  1. Si tiene que anular alguno de estos Hilo métodos como se enumeran en la página de documentación de Oracle

Por lo general, no es necesario anular el comportamiento de Thread. Entonces implementa Runnable se prefiere la mayoría de las veces.

En una nota diferente, usando avanzado ExecutorService or ThreadPoolExecutorService API proporciona más flexibilidad y control.

Eche un vistazo a esta pregunta SE:

ExecutorService vs Generador de hilo casual

contestado el 23 de mayo de 17 a las 12:05

Separar la clase Thread de la implementación Runnable también evita posibles problemas de sincronización entre el hilo y el método run (). Un Runnable separado generalmente brinda una mayor flexibilidad en la forma en que se hace referencia y se ejecuta el código ejecutable.

respondido 08 mar '10, 07:03

Runnable es una interfaz, mientras que Thread es una clase que implementa esta interfaz. Desde el punto de vista del diseño, debe haber una clara separación entre cómo se define una tarea y cómo se ejecuta. El primero es responsabilidad de un Runnalbe implementación, y este último es trabajo del Thread clase. En la mayoría de los casos, la implementación Runnable es el camino correcto a seguir.

Respondido 18 ago 12, 18:08

Eso es S of SOLID: Responsabilidad única.

A hilo encarna el contexto de ejecución (como en el contexto de ejecución: marco de pila, id de hilo, etc.) del ejecución asincrónica de un fragmento de código. Que fragmento de código idealmente debería ser la misma implementación, ya sea sincrónico or asincrónico.

Si los agrupa en una implementación, le da al objeto resultante dos no relacionado causas del cambio:

  1. manejo de subprocesos en su aplicación (es decir, consultar y modificar el contexto de ejecución)
  2. algoritmo implementado por el fragmento de código (la parte ejecutable)

Si el lenguaje que usa admite clases parciales o herencia múltiple, entonces puede segregar cada causa en su propia superclase, pero se reduce a lo mismo que componer los dos objetos, ya que sus conjuntos de características no se superponen. Eso es por la teoría.

En la práctica, en términos generales, un programa no necesita ser más complejo de lo necesario. Si tiene un hilo trabajando en una tarea específica, sin cambiar esa tarea, probablemente no tenga sentido hacer que las tareas sean clases separadas, y su código sigue siendo más simple.

En el contexto de los Java, ya que la instalación es ya ahi, probablemente sea más fácil comenzar directamente con el modo autónomo Runnable clases y pasar sus instancias a Thread (o Executor) instancias. Una vez usado para ese patrón, no es más difícil de usar (o incluso leer) que el simple caso de subprocesos ejecutables.

contestado el 11 de mayo de 13 a las 09:05

Una razón por la que querría implementar una interfaz en lugar de extender una clase base es que ya está extendiendo alguna otra clase. Solo puede extender una clase, pero puede implementar cualquier cantidad de interfaces.

Si extiende Thread, básicamente está evitando que su lógica sea ejecutada por cualquier otro hilo que no sea 'this'. Si solo quieres algo hilo para ejecutar su lógica, es mejor simplemente implementar Runnable.

Respondido 25 Jul 13, 18:07

Sí, al implementar la interfaz Runnable, puede implementar su propia lógica al extender cualquier clase, por eso se prefiere Runnable sobre la clase Thread. - Akash5288

si usa runnable, puede guardar el espacio para extenderlo a cualquiera de sus otras clases.

Respondido el 26 de Septiembre de 13 a las 06:09

¿Podemos volver a visitar la razón básica por la que queríamos que nuestra clase se comportara como un Thread? No hay ninguna razón, solo queríamos ejecutar una tarea, muy probablemente en modo asincrónico, lo que significa precisamente que la ejecución de la tarea debe ramificarse desde nuestro hilo principal y el hilo principal si termina antes, puede o no esperar. para la ruta ramificada (tarea).

Si este es todo el propósito, entonces ¿dónde veo la necesidad de un hilo especializado? Esto se puede lograr tomando un hilo RAW del grupo de hilos del sistema y asignándole nuestra tarea (puede ser una instancia de nuestra clase) y eso es todo.

Así que obedezcamos el concepto de POO y escribamos una clase del tipo que necesitamos. Hay muchas formas de hacer las cosas, hacerlo de la manera correcta es importante.

Necesitamos una tarea, así que escriba una definición de tarea que se pueda ejecutar en un subproceso. Entonces usa Runnable.

Recuerda siempre implements se utiliza especialmente para impartir un comportamiento y extends se utiliza para impartir una característica / propiedad.

No queremos la propiedad del hilo, sino que queremos que nuestra clase se comporte como una tarea que se puede ejecutar.

respondido 22 nov., 13:03

Sí, si llama a ThreadA, entonces no es necesario llamar al método de inicio y el método de ejecución es una llamada después de llamar a la clase ThreadA solamente. Pero si usa la llamada ThreadB, entonces necesita el hilo de inicio para el método de ejecución de la llamada. Si tienes más ayuda, respóndeme.

Respondido el 28 de enero de 12 a las 08:01

Encuentro que es más útil usar Runnable por todas las razones mencionadas, pero a veces me gusta extender Thread para poder crear mi propio método de detención de subprocesos y llamarlo directamente en el subproceso que he creado.

Respondido el 09 de junio de 12 a las 20:06

Java no admite herencia múltiple, por lo que si extiende la clase Thread, no se extenderá ninguna otra clase.

Por ejemplo: si crea un subprograma, debe extender la clase de subprograma, por lo que aquí la única forma de crear un hilo es implementando la interfaz Runnable

Respondido el 09 de junio de 12 a las 20:06

Diferencia entre Thread y ejecutable. Si estamos creando Thread usando la clase Thread, entonces Número de hilo es igual al número de objeto que creamos. Si estamos creando subprocesos implementando la interfaz ejecutable, entonces podemos usar un solo objeto para crear múltiples subprocesos, por lo que un solo objeto es compartido por múltiples subprocesos, por lo que tomará menos memoria

Entonces, dependiendo del requisito si nuestros datos no son sensibles. Por lo tanto, se puede compartir entre varios subprocesos, podemos usar la interfaz Runnable.

respondido 05 mar '14, 06:03

Añadiendo mis dos centavos aquí - Siempre que sea posible utilizar implements Runnable . A continuación se presentan dos advertencias sobre por qué no debe usar extends Threads

  1. Idealmente, nunca debería extender la clase Thread; la Thread la clase debe hacerse final. Al menos sus métodos como thread.getId(). Ver este discusión sobre un error relacionado con la extensión Threads.

  2. Aquellos a quienes les gusta resolver acertijos pueden ver otro efecto secundario de extender Thread. El siguiente código imprimirá un código inalcanzable cuando nadie les notifique.

Por favor mira http://pastebin.com/BjKNNs2G.

public class WaitPuzzle {

    public static void main(String[] args) throws InterruptedException {
        DoNothing doNothing = new DoNothing();
        new WaitForever(doNothing).start();
        new WaitForever(doNothing).start();
        new WaitForever(doNothing).start();
        Thread.sleep(100);
        doNothing.start();
        while(true) {
            Thread.sleep(10);
        }
    }


    static class WaitForever extends  Thread {

        private DoNothing doNothing;

        public WaitForever(DoNothing doNothing) {
            this.doNothing =  doNothing;
        }

        @Override
        public void run() {
            synchronized (doNothing) {
                try {
                    doNothing.wait(); // will wait forever here as nobody notifies here
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Unreachable Code");
            }
        }
    }

    static class DoNothing extends Thread {

        @Override
        public void run() {
            System.out.println("Do Nothing ");
        }
    } 
}

Respondido el 03 de enero de 15 a las 09:01

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.