"implements Runnable" vs "extends 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

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

Author: Steve Chambers, 2009-02-12

30 answers

Sí: implementa Runnable es la forma preferida de hacerlo, IMO. No estás realmente especializando el comportamiento del hilo. Sólo le estás dando algo para correr. Eso significa quela composición es elfilosóficamente camino "más puro" a seguir.

En términos prácticos , significa que puede implementarRunnable y extender desde otra clase también.

 1466
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-22 22:09:24

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

En general, recomendaría usar algo como Runnable en lugar de Thread porque le permite mantener su trabajo solo vagamente acoplado con su elección de concurrencia. Por ejemplo, si usas un Runnable y decides más tarde que esto no requiere que sea propio Thread, puedes llamar a ThreadA.ejecutar().

Advertencia: Por aquí, desaconsejo fuertemente el uso de raw Hilo. Prefiero mucho el uso de Callables y FutureTasks (del javadoc: "Un cálculo asíncrono cancelable"). La integración de los tiempos de espera, la cancelación adecuada y la agrupación de subprocesos del soporte de concurrencia moderna son mucho más útiles para mí que las pilas de subprocesos sin procesar.

Seguimiento: 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 modernas de concurrencia. 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 su runnable con su threadA, obtenemos lo siguiente:

new FutureTask<Object>(threadA, null)

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

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

ExecutorService es = Executors.newCachedThreadPool();
es.execute(new ThreadA());
 500
Author: Bob Cross,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-28 07:26:50

Moraleja de la historia:

Heredar solo si desea anular algún comportamiento.

O más bien debe leerse como:

Heredar menos, interactuar más.

 232
Author: panzerschreck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-28 16:26:50

Bueno, muchas buenas respuestas, quiero agregar más sobre esto. Esto ayudará a entender Extending v/s Implementing Thread.
Extends enlaza dos archivos de clase muy de cerca y puede causar que algunos sean bastante difíciles de tratar con el código.

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 un espacio para que su clase extienda cualquier otra clase en el futuro o ahora.

Sin embargo, una diferencia significativa entre implementar Ejecutable y extender Hilo 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 ayuda a entender más claramente

//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 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 interfaz ejecutable, solo una instancia de un la clase se está creando y ha sido compartida por diferentes hilos. Por lo tanto, el valor del contador se incrementa para cada acceso a subprocesos.

Considerando que, enfoque de clase de subproceso, debe tener que crear una instancia separada para cada acceso de subproceso. Por lo tanto, se asigna una 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 del objeto es la misma.

Cuándo usar ¿Ejecutable?
Utilice la interfaz ejecutable cuando desee acceder al mismo recurso desde el grupo de subprocesos. Evite usar la clase Thread aquí, porque la creación de múltiples objetos consume más memoria y se convierte en una gran sobrecarga de rendimiento.

Una clase que implementa Runnable no es un subproceso sino solo una clase. Para que un Ejecutable se convierta en un Subproceso, debe crear una instancia de Subproceso y pasar a sí mismo como destino.

En la mayoría de los casos, se debe usar la interfaz ejecutable si solo está planeando sobreescribir el método run() y ningún otro método de Subproceso. Esto es importante porque las clases no deben ser subclases a menos que el programador tenga la intención de modificar o mejorar el comportamiento fundamental de la clase.

Cuando es necesario extender una superclase, implementar la interfaz Ejecutable es más apropiado que usar la clase Thread. Porque podemos extender otra clase mientras implementamos una interfaz ejecutable para hacer un subproceso.

Espero que esto ¡ayudará!

 189
Author: Rupesh Yadav,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-11 10:47:33

Una cosa que me sorprende que no se haya mencionado todavía es que implementar Runnable hace que su clase sea más flexible.

Si extiendes el hilo, entonces la acción que estás haciendo siempre estará en un hilo. Sin embargo, si implementa Runnable no tiene que ser. Puede ejecutarlo en un subproceso, o pasarlo a algún tipo de servicio ejecutor, o simplemente pasarlo como una tarea dentro de una sola aplicación enhebrada (tal vez para ejecutarse en un momento posterior, pero dentro del mismo subproceso). Las opciones son mucho más abierto si solo usas Runnable que si te atas a Thread.

 73
Author: Herms,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-12 12:53:26

Si desea implementar o extender cualquier otra clase, entonces la interfaz Runnable es preferible de otro modo si no desea que ninguna otra clase se extienda o implemente, entonces Thread la clase es preferible

La diferencia más común es

introduzca la descripción de la imagen aquí

Cuando usted extends Thread clase, después de que usted no puede extender cualquier otra clase que usted requiere. (Como sabes, Java no permite heredar más de una clase).

Cuando usted implements Runnable, puede ahorrar un espacio para su clase para extender cualquier otra clase en el futuro o ahora.

  • Java no admite herencia múltiple, 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, modificar o mejorar comportamientos. Si no estamos haciendo ninguna modificación en el hilo, utilice la interfaz ejecutable en su lugar.

  • La interfaz ejecutable representa una Tarea que puede ser ejecutada por Subprocesos simples o Ejecutores o por cualquier otro medio. así que la separación lógica de la tarea como Ejecutable de hilo es una buena decisión de diseño.

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

  • Java el diseñador reconoce esto y es por eso que los ejecutores aceptan Runnable como Tarea y tienen worker thread que ejecuta esas tareas.

  • Heredar todos los métodos de subproceso 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 otras diferencias en Thread vs Runnable que por favor, compártalo a través de comentarios. Yo personalmente uso Runnable sobre hilo para este escenario y recomienda utilizar Runnable o interfaz llamable basado en su requisito.

Sin Embargo, la diferencia significativa es.

Cuando haces una clase extends Thread, cada uno de tus subprocesos crea un objeto único y se asocia con él. Cuando implements Runnable, comparte el mismo objeto en varios subprocesos.

 66
Author: Nidhish Krishnan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-21 15:02:55

En realidad, no es sabio comparar Runnable y Thread entre sí.

Estos dos tienen una dependencia y relación en multi-threading al igual que Wheel and Engine relación de vehículo de motor.

Yo diría que solo hay una forma de multi-threading con dos pasos. Déjame exponer mi punto.

Ejecutable:
Al implementar interface Runnable significa que estás creando algo que está run able en un hilo diferente. Ahora creando algo que puede funcionar dentro de un thread (ejecutable dentro de un hilo), no significa crear un hilo.
Así que la clase MyRunnable no es más que una clase ordinaria con un método void run. 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 hilo que en realidad permite multi-threading a través de su start() método.

¿Por qué no es sabio comparar?
Porque los necesitamos para multi-threading.

Para Multi-threading necesitamos dos cosas:

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

Así que técnica y teóricamente ambos son necesarios para iniciar un subproceso, uno correrá y uno lo hará correr (Como Wheel and Engine de motor vehículo).

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 la clase Thread implementa Runnable así que todos sabemos que Thread también es un Runnable dentro.

Finalmente Thread y Runnable se complementan entre sí para multihilo no competidor o reemplazo.

 61
Author: Saif,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-03 05:58:59

Debe implementar Runnable, pero si se está ejecutando en Java 5 o superior, no debe iniciarlo con new Thread sino usar un ExecutorService en su lugar. Para más detalles vea: Cómo implementar el subproceso simple en Java.

 41
Author: Fabian Steeg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:26:36

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

Edit: Esto originalmente decía "Implementar una interfaz requiere menos recursos."también, pero necesitas crear una nueva instancia de subproceso de cualquier manera, así que esto estuvo mal.

 31
Author: Powerlord,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-12 14:32:01

Yo diría que hay una tercera manera:

public class Something {

    public void justAnotherMethod() { ... }

}

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

Tal vez esto está influenciado un poco 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.

 19
Author: Bart van Heukelom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-25 21:41:00

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

Runnable es una interfaz funcional , lo que significa que las instancias de la misma se pueden crear con expresiones lambda o referencias de métodos.

Su ejemplo puede ser reemplazado por:

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

O si desea utilizar 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 sobre Thread, como la responsabilidad individual y el uso de la composición porque no estás especializando el comportamiento del hilo. De esta manera también evita crear una clase extra si todo lo que necesita es un Runnable como lo hace en sus ejemplos.

 16
Author: Alex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-05 12:10:44

Crear una instancia de una interfaz da una separación más limpia entre su código y la implementación de subprocesos, por lo que preferiría implementar Runnable en este caso.

 15
Author: starblue,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-12 14:33:09
  1. Java no admite herencia múltiple, 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.
  2. En la programación orientada a objetos extender una clase generalmente significa agregar nueva funcionalidad, modificar o mejorar comportamientos. Si no estamos haciendo ninguna modificación en Thread entonces use la interfaz Runnable en su lugar.
  3. Runnable interfaz representa un Task que puede ser ejecutado por Thread o Executors o por cualquier otro medio. Así que la separación lógica de Task como Runnable que Thread es una buena decisión de diseño.
  4. Separar la tarea como Runnable significa que podemos reutilizar la tarea y también tenemos libertad para ejecutarla desde diferentes medios. Dado que no puede reiniciar un Thread una vez que se complete, nuevamente Runnable vs Thread para la tarea, Runnable es el ganador.
  5. Java designer reconoce esto y es por eso que Executors acepta Runnable como Task y tienen worker thread que ejecuta aquellos tarea.
  6. Heredar todos los métodos Thread es una sobrecarga adicional solo para representar un Task que se puede hacer fácilmente con Runnable.
 12
Author: Hutashan Chandrakar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-21 15:45:57

Ejecutable porque:

  • Deja más flexibilidad para el Implementación ejecutable para extender otra clase
  • Separa el código de ejecución
  • le Permite ejecutar su ejecutable desde un grupo de subprocesos, el event thread, o de cualquier otra manera en futuro.

Incluso si usted no necesita nada de esto ahora, usted puede en el futuro. Dado que no hay ningún beneficio en sobreescribir el hilo, Runnable es una mejor solución.

 10
Author: n13,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-05-07 04:28:57

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 el hilo en mi opinión, de hecho, lo has demostrado en tu código.

Si implementas Runnable entonces 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 extiendes Thread entonces puedes manejar esto dentro de la clase en sí mismo (al igual que en tu ejemplo nombras el hilo 'ThreadB'). En este caso usted:

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

B) están forzando 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 Ejecutable, pero estamos hablando de convención aquí en cualquier caso, así que puede ignorar esa posibilidad que siento).

Incluso podrías, por ejemplo, tomar un rastro de pila de su creación y usa eso como el 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 donde tiene una aplicación muy compleja con una gran cantidad de hilos y, de repente, las cosas ' se han detenido '(ya sea por razones de bloqueo o posiblemente debido a un defecto en un protocolo de red que sería menos obvio - u otras razones interminables), a continuación, obtener un volcado de pila de Java donde todos los hilos se llaman 'Thread-1','Thread-2', 'Thread-3' no siempre es muy útil (depende de cómo se estructuran sus subprocesos y si puede decir útilmente cuál es cuál solo por su seguimiento de pila - no siempre es posible si está utilizando grupos de múltiples subprocesos todos corriendo el mismo código).

Dicho esto, por supuesto, también podría hacer lo anterior de una manera genérica creando una extensión de la clase thread que establezca su nombre en un rastro de pila de su llamada de creación y luego usarlo con sus implementaciones ejecutables en lugar de la clase de subproceso java estándar (ver a continuación), pero además del seguimiento de pila, podría haber más información específica del contexto que sería útil en el nombre del subproceso 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 extender el subproceso específicamente para ese caso para que pueda hacer que el compilador lo obligue (u otros que usen sus bibliotecas) a pasar cierta información (por ejemplo, la cola / socket en cuestión) para su uso en el nombre).

Aquí hay un ejemplo del subproceso genérico con la llamada stack trace 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 comparando 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]
 10
Author: AntonyM,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-19 23:12:49

Dado que este es un tema muy popular y las buenas respuestas se extienden por todas partes y se tratan en gran profundidad, sentí que es justificable compilar las buenas respuestas de los demás en una forma más concisa, para que los recién llegados tengan una visión general fácil por adelantado:

  1. Por lo general, se extiende una clase para agregar o modificar la funcionalidad. Por lo tanto, si no quieres para sobrescribir cualquier comportamiento del hilo, entonces usa Runnable.

  2. En la misma luz, si no necesita para heredar métodos de subproceso, puede prescindir de overhead usando Runnable.

  3. Single inheritance : Si extiende Thread no puede extender 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 de dominio de los medios técnicos, en ese sentido es mejor tener una tarea ejecutable aislando su tarea de su runner .

  5. Puede ejecutarel mismo objeto ejecutable varias veces, sin embargo, un objeto Thread solo se puede iniciar una vez. (Tal vez la razón, por qué los ejecutores aceptan Runnables, pero no Threads.)

  6. Si desarrolla su tarea como Ejecutable, tiene toda la flexibilidad para usarla ahora y en el futuro. Puedes hacer que se ejecute simultáneamente a través de ejecutores, pero también a través de Subprocesos. Y aún así también podría usar / llamarlo no concurrentemente dentro del mismo hilo como cualquier otro tipo/objeto ordinario.

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

  8. Si está interesado en esta pregunta, también podría estar interesado en la diferencia entre Callable y Runnable.

 10
Author: Jörg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:26:36

Esto se discute en el tutorial de Oracle Definiendo e iniciando un Hilo :

¿Cuál de estos modismos deberías usar? El primer idioma, que emplea un Objeto ejecutable, es más general, porque el objeto ejecutable puede subclase 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 tarea la clase debe ser un descendiente de Thread. Esta lección se centra en la primera enfoque, que separa la Tarea ejecutable desde el objeto Thread que ejecuta la tarea. Este enfoque no solo es más flexible, sino que es aplicable a las API de gestión de subprocesos de alto nivel cubiertas tarde.

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

 8
Author: Sionnach733,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-21 16:44:09

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

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

Extends establece " Es Una relación" y la interfaz proporciona " Tiene una capacidad".

Prefiere implements Runnable :

  1. Si no tienes que extender la clase Thread y modificar la implementación predeterminada de la API Thread
  2. Si estás ejecutando un fuego y olvidas la orden
  3. Si ya están extendiendo otra clase

Prefiere "extiende el Hilo" :

  1. Si tiene que anular cualquiera de estos métodos Thread como se indica en la página de documentación de oracle

Generalmente no es necesario anular el comportamiento del hilo. Así que implementa Runnable es preferible para la mayoría de las veces.

En una nota diferente, el uso de API avanzada ExecutorService o ThreadPoolExecutorService proporciona más flexibilidad y control.

Echa un vistazo a esta Pregunta SE:

ExecutorService vs Casual Thread Spawner

 6
Author: Ravindra babu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:47:31

Las diferencias entre Extender el Hilo e Implementar Ejecutable son:

introduzca la descripción de la imagen aquí

 6
Author: Raman Gupta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-01 15:05:06

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

 5
Author: Govula Srinivas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-08 07:03:06

Una de las razones por las que desea 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 número de interfaces.

Si extiendes el subproceso, básicamente estás evitando que tu lógica sea ejecutada por cualquier otro subproceso que no sea 'this'. Si solo quieres algún subproceso para ejecutar tu lógica, es mejor simplemente implementar Runnable.

 5
Author: Nikhil A A,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-25 17:29:00

Si usas runnable puedes ahorrar espacio para extenderlo a cualquiera de tus otras clases.

 5
Author: user2771655,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-26 05:58:02

¿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 en absoluto, solo queríamos ejecutar una tarea, lo más probable en un modo asíncrono, lo que significa precisamente que la ejecución de la tarea debe ramificarse desde nuestro hilo principal y el hilo principal si termina temprano, puede o no puede esperar 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 recogiendo un CRUDO Thread del Grupo de subprocesos del Sistema y asignándole nuestra tarea (puede ser una instancia de nuestra clase) y eso es todo.

Así que obedezcamos el concepto OOPs y escribamos una clase del tipo que necesitamos. Hay muchas maneras de hacer las cosas, hacerlo de la manera correcta importa.

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

Siempre recuerde que implements se usa especialmente para impartir un comportamiento y extends se usa para impartir un característica / propiedad.

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

 5
Author: dharam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-22 03:11:51

Sí, Si llama a ThreadA call, entonces no necesita llamar al método start y el método run es llamar después de llamar a la clase ThreadA solamente. Pero si usa la llamada ThreadB, entonces necesita el hilo de inicio necesario para el método call run. Si tienes más ayuda, contéstame.

 4
Author: Manoj Kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-28 08:31:16

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

 4
Author: Tarvaris Jackson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-09 19:09:15

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 applet, entonces debe extender la clase Applet, así que aquí la única manera de crear un subproceso es implementando la interfaz ejecutable

 4
Author: Himanshu Mohta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-09 19:28:31

Ese es el S de SÓLIDO: Responsabilidad única.

Un thread encarna el contexto en ejecución (como en el contexto de ejecución: marco de pila, id de hilo, etc.) de la ejecución asíncrona de un fragmento de código. Esa pieza de código idealmente debería ser la misma implementación, ya sea síncrona o asíncrona.

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

  1. manejo de subprocesos en su aplicación (es decir. consulta y modificación del contexto de ejecución)
  2. algoritmo implementado por la pieza 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 llevar más complejidad de la necesaria. Si tiene un subproceso trabajando en una tarea específica, sin cambiar esa tarea, probablemente no tenga sentido hacer que las tareas separen clases, y su código siga siendo más simple.

En el contexto de Java , dado que la instalación ya está , probablemente sea más fácil comenzar directamente con las clases independientes Runnable, y pasar sus instancias a Thread (o Executor) instancias. Una vez que utiliza para ese patrón, no es más difícil de usar (o incluso leer) que el simple caso de hilo ejecutable.

 4
Author: didierc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-11 08:41:39

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

Así que dependiendo del requisito si nuestros datos no son sensibles. Por lo que se puede compartir entre varios Subprocesos podemos utilizar Runnable interfaz.

 4
Author: Rohit Chugh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-05 06:13:58

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

  1. Lo ideal es que nunca se extienda la clase Thread; la clase Thread debe hacerse final. Al menos sus métodos como thread.getId(). Ver esta discusión para un error relacionado con la extensión de Thread s.

  2. Aquellos que les gusta resolver puzzles pueden ver otro efecto secundario de extender el hilo. El siguiente código se imprimirá inalcanzable código cuando nadie les está notificando.

Véase 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 ");
        }
    } 
}
 4
Author: veritas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-03 09:41:19

Una diferencia entre implementar Runnable y extender Thread es que al extender Thread, cada uno de tus threads tiene un objeto único asociado, mientras que implementar Runnable, muchos threads pueden compartir la misma instancia de objeto.

Una clase que implementa Runnable no es un subproceso sino solo una clase. Para que un Ejecutable sea ejecutado por un Subproceso, debe crear una instancia de Subproceso y pasar la instancia Ejecutable como destino.

En la mayoría de los casos, el ejecutable la interfaz debe ser usada si solo estás planeando sobreescribir el método run () y ningún otro método Thread. Esto es importante porque las clases no deben ser subclases a menos que el programador tenga la intención de modificar o mejorar el comportamiento fundamental de la clase.

Cuando es necesario extender una superclase, implementar la interfaz Ejecutable es más apropiado que usar la clase Thread. Porque podemos extender otra clase mientras implementamos una interfaz ejecutable para hacer un subproceso. Pero si solo extendemos la clase Thread no podemos heredar de ninguna otra clase.

 4
Author: Vishal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-03 13:46:02