“Implements Runnable” vs. “extends Thread”

Da che ora ho trascorso con i thread in Java, ho trovato questi due modi per scrivere thread:

Con gli implements Runnable :

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

Oppure, con extends Thread :

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

C’è qualche differenza significativa in questi due blocchi di codice?

    Sì: implements Runnable è il modo preferito per farlo, IMO. Non stai davvero specializzando il comportamento del thread. Stai solo dando qualcosa da eseguire. Ciò significa che la composizione è la via filosoficamente più “pura” da percorrere.

    In termini pratici , significa che puoi implementare Runnable ed estenderlo anche da un’altra class.

    tl; dr: implements Runnable è migliore. Tuttavia, l’avvertenza è importante

    In generale, consiglierei di usare qualcosa come Runnable piuttosto che Thread perché ti permette di mantenere il tuo lavoro solo in modo approssimativo con la tua scelta di concorrenza. Ad esempio, se si utilizza un Runnable e si decide in seguito che questo non richiede in effetti il ​​proprio Thread , è sufficiente chiamare threadA.run ().

    Avvertenza: da queste parti, scoraggio vivamente l’uso di thread grezzi. Preferisco di gran lunga l’uso di Callables e FutureTasks (da javadoc: “Un calcolo asincrono cancellabile”). L’integrazione di timeout, cancellazione appropriata e il pooling di thread del moderno supporto di concorrenza sono molto più utili per me di pile di thread non elaborati.

    Follow-up: esiste un costruttore FutureTask che consente di utilizzare Runnables (se è quello con cui si è più a proprio agio) e ottenere comunque il beneficio dei moderni strumenti di concorrenza. Per citare il javadoc:

    Se non hai bisogno di un risultato particolare, considera l’utilizzo di costruzioni del modulo:

     Future f = new FutureTask(runnable, null) 

    Quindi, se sostituiamo il loro runnable con il tuo threadA , otteniamo quanto segue:

     new FutureTask(threadA, null) 

    Un’altra opzione che ti permette di stare più vicino a Runnables è un ThreadPoolExecutor . Puoi usare il metodo execute per passare un Runnable per eseguire “l’attività assegnata in futuro”.

    Se desideri provare a utilizzare un pool di thread, il frammento di codice sopra riportato diventerà simile al seguente (utilizzando il metodo factory Executors.newCachedThreadPool () ):

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

    Morale della storia:

    Eredita solo se vuoi sovrascrivere un comportamento.

    O meglio dovrebbe essere letto come:

    Eredita di meno, interfaccia di più.

    Bene, tante buone risposte, voglio aggiungere altro su questo. Questo aiuterà a capire l’ Extending v/s Implementing Thread .
    Extends lega molto strettamente due file di class e può causare alcuni problemi con il codice.

    Entrambi gli approcci fanno lo stesso lavoro ma ci sono state alcune differenze.
    La differenza più comune è

    1. Quando si estende la class Thread, dopo di che non è ansible estendere qualsiasi altra class richiesta. (Come sai, Java non consente di ereditare più di una class).
    2. Quando implementi Runnable, puoi salvare uno spazio affinché la tua class estenda qualsiasi altra class in futuro o ora.

    Tuttavia, una differenza significativa tra l’implementazione di Thread eseguibile ed esteso è quella
    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.

    Il seguente esempio ti aiuta a capire più chiaramente

     //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 classs 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(); } } 

    Uscita del programma di cui sopra.

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

    Nell’approccio Runnable interface, viene creata una sola istanza di una class ed è stata condivisa da thread diversi. Quindi il valore del contatore viene incrementato per ogni accesso al thread.

    Considerando che, l’approccio della class Thread, è necessario creare un’istanza separata per ogni accesso al thread. Quindi la memoria diversa è allocata per ogni istanza di class e ciascuno ha un contatore separato, il valore rimane lo stesso, il che significa che non si verificherà alcun incremento perché nessuno del riferimento all’object è lo stesso.

    Quando usare Runnable?
    Utilizzare l’interfaccia Runnable quando si desidera accedere alla stessa risorsa dal gruppo di thread. Evita di usare la class Thread qui, perché la creazione di più oggetti consuma più memoria e diventa un big overhead delle prestazioni.

    Una class che implementa Runnable non è un thread e solo una class. Affinché un Runnable diventi un thread, è necessario creare un’istanza di Thread e passarsi come target.

    Nella maggior parte dei casi, è consigliabile utilizzare l’interfaccia Runnable se si prevede di sovrascrivere il metodo run() e nessun altro metodo Thread. Questo è importante perché le classi non dovrebbero essere sottoclassate a meno che il programmatore non intenda modificare o migliorare il comportamento fondamentale della class.

    Quando è necessario estendere una superclass, l’implementazione dell’interfaccia Runnable è più appropriata rispetto all’utilizzo della class Thread. Perché possiamo estendere un’altra class mentre implementiamo l’interfaccia Runnable per creare un thread.

    Spero che questo ti possa aiutare!

    Una cosa che mi sorprende non è stata ancora menzionata è che l’implementazione di Runnable rende la tua class più flessibile.

    Se estendi il thread, l’azione che stai facendo sarà sempre in una discussione. Tuttavia, se si implementa Runnable , non è necessario. È ansible eseguirlo in un thread o passarlo a qualche tipo di servizio executor, o semplicemente passarlo come attività all’interno di una singola applicazione a thread (magari per essere eseguito in un secondo momento, ma all’interno dello stesso thread). Le opzioni sono molto più aperte se usi Runnable piuttosto che se ti leghi a Thread .

    Se si desidera implementare o estendere qualsiasi altra class, l’interfaccia Runnable è preferibile se non si desidera che qualsiasi altra class si estenda o implementa, quindi è preferibile la class Thread

    La differenza più comune è

    inserisci la descrizione dell'immagine qui

    Quando si extends Thread class extends Thread , dopo di che non è ansible estendere qualsiasi altra class richiesta. (Come sai, Java non consente di ereditare più di una class).

    Quando implements Runnable , puoi salvare uno spazio affinché la tua class estenda qualsiasi altra class in futuro o ora.

    • Java non supporta l’ereditarietà multipla, il che significa che puoi estendere una sola class in Java, quindi una volta estesa la class Thread hai perso le possibilità e non puoi estendere o ereditare un’altra class in Java.

    • Nella programmazione orientata agli oggetti estendere una class in genere significa aggiungere nuove funzionalità, modificare o migliorare i comportamenti. Se non apportiamo alcuna modifica a Thread, utilizza invece l’interfaccia Runnable.

    • L’interfaccia eseguibile rappresenta un’attività che può essere eseguita sia da Thread normale che da Executor o qualsiasi altro mezzo. la separazione logica di Task come Runnable che Thread è una buona decisione di progettazione.

    • Separare il compito come Runnable significa che possiamo riutilizzare il compito e avere anche la libertà di eseguirlo da diversi mezzi. dal momento che non è ansible riavviare una discussione una volta completata. ancora Runnable vs Thread per task, Runnable è vincitore.

    • Designer Java riconosce questo ed è per questo che gli esecutori accettano Runnable as Task e hanno thread di lavoro che esegue tali attività.

    • Ereditare tutti i metodi Thread è un overhead aggiuntivo solo per rappresentare un’attività che può essere eseguita facilmente con Runnable.

    Per gentile concessione di javarevisited.blogspot.com

    Queste erano alcune delle notevoli differenze tra Thread e Runnable in Java, se si conoscono altre differenze su Thread vs Runnable, si prega di condividerle tramite commenti. Personalmente utilizzo Runnable su Thread per questo scenario e mi consiglia di utilizzare l’interfaccia Runnable o Callable in base alle tue esigenze.

    Tuttavia, la differenza significativa è.

    Quando extends Thread class extends Thread , ciascun thread crea un object univoco e si associa ad esso. Quando implements Runnable , condivide lo stesso object su più thread.

    In realtà, non è saggio confrontare Runnable e Thread uno con l’altro.

    Questi due hanno una dipendenza e una relazione nel multi-threading proprio come il rapporto tra Wheel and Engine del veicolo a motore.

    Direi, esiste un solo modo per il multi-threading con due passaggi. Lasciatemi esprimere il mio punto.

    Runnable:
    Quando si implementa l’ interface Runnable significa che si sta creando qualcosa che può essere run able in un thread diverso. Ora creare qualcosa che può essere eseguito all’interno di un thread (eseguibile in un thread), non significa creare un Thread.
    Quindi la class MyRunnable non è altro che una class ordinaria con un metodo di void run . E gli oggetti saranno oggetti ordinari con solo un metodo run che verrà eseguito normalmente quando chiamato. (a meno che non passiamo l’object in un thread).

    Filo:
    class Thread , direi Una class molto speciale con la capacità di avviare una nuova discussione che consente effettivamente il multi-threading attraverso il suo metodo start() .

    Perché non saggio da confrontare?
    Perché abbiamo bisogno di entrambi per il multi-threading.

    Per il multi-threading abbiamo bisogno di due cose:

    • Qualcosa che può essere eseguito all’interno di un thread (eseguibile).
    • Qualcosa che può iniziare una nuova discussione (discussione).

    Quindi tecnicamente e teoricamente entrambi sono necessari per iniziare un thread, uno verrà eseguito e uno lo farà funzionare (come Wheel and Engine of motor vehicle).

    Ecco perché non puoi avviare un thread con MyRunnable devi passarlo a un’istanza di Thread .

    Ma è ansible creare ed eseguire un thread usando solo la class Thread perché la class Thread implementa Runnable quindi sappiamo tutti che Thread è anche Runnable all’interno.

    Infine Thread e Runnable sono complementari l’un l’altro per il multithreading non concorrente o sostitutivo.

    Dovresti implementare Runnable, ma se stai usando Java 5 o versioni successive, non dovresti avviarlo con il new Thread ma usare invece un ExecutorService . Per i dettagli vedere: Come implementare il threading semplice in Java .

    Non sono un esperto, ma posso pensare a un motivo per implementare Runnable anziché estendere Thread: Java supporta solo l’ereditarietà singola, quindi puoi estendere solo una class.

    Modifica: originariamente detto “L’implementazione di un’interfaccia richiede meno risorse”. pure, ma è necessario creare una nuova istanza di Thread in entrambi i casi, quindi questo era sbagliato.

    Direi che c’è una terza via:

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

    Forse questo è influenzato un po ‘dal mio recente uso pesante di Javascript e Actionscript 3, ma in questo modo la tua class non ha bisogno di implementare un’interfaccia piuttosto vaga come Runnable .

    Con il rilascio di Java 8, ora c’è una terza opzione.

    Runnable è un’interfaccia funzionale , il che significa che le sue istanze possono essere create con espressioni lambda o riferimenti al metodo.

    Il tuo esempio può essere sostituito con:

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

    o se si desidera utilizzare un ExecutorService e un riferimento al metodo:

     executor.execute(runner::run) 

    Questi sono non solo molto più brevi dei tuoi esempi, ma hanno anche molti dei vantaggi dichiarati in altre risposte sull’uso di Runnable over Thread , come la responsabilità singola e l’uso della composizione perché non stai specializzando il comportamento del thread. In questo modo evita anche di creare una class extra se tutto ciò che ti serve è un Runnable come fai nei tuoi esempi.

    L’istanziazione di un’interfaccia offre una separazione più chiara tra il codice e l’implementazione dei thread, quindi in questo caso preferirei implementare Runnable.

    1. Java non supporta l’ereditarietà multipla, il che significa che puoi estendere una sola class in Java, quindi una volta estesa la class Thread hai perso le possibilità e non puoi estendere o ereditare un’altra class in Java.
    2. Nella programmazione orientata agli oggetti estendere una class in genere significa aggiungere nuove funzionalità, modificare o migliorare i comportamenti. Se non stiamo apportando alcuna modifica su Thread di usare l’interfaccia Runnable .
    3. Runnable interfaccia eseguibile rappresenta un’attività che può essere eseguita sia da Thread normale che da Executors o qualsiasi altro mezzo. Quindi la separazione logica di Task come Runnable che Thread è una buona decisione di progettazione.
    4. Separare il compito come Runnable significa che possiamo riutilizzare il compito e avere anche la libertà di eseguirlo da diversi mezzi. Poiché non è ansible riavviare una Thread una volta completata, ancora Runnable vs Thread per attività, Runnable è vincente.
    5. Designer Java riconosce questo ed è per questo che gli Executors accettano Runnable as Task e hanno thread di lavoro che esegue tali attività.
    6. Ereditare tutti i metodi Thread è un overhead aggiuntivo solo per rappresentare un’attività che può essere eseguita facilmente con Runnable .

    Runnable perché:

    • Lascia più flessibilità all’implementazione Runnable per estendere un’altra class
    • Separa il codice dall’esecuzione
    • Ti permette di eseguire il tuo runnable da un pool di thread, il thread dell’evento o in qualsiasi altro modo in futuro.

    Anche se non hai più bisogno di questo, puoi farlo in futuro. Poiché non c’è alcun vantaggio nel sovrascrivere Thread, Runnable è una soluzione migliore.

    Tutti qui sembrano pensare che implementare Runnable sia la strada da percorrere e io non sono affatto in disaccordo con loro, ma a mio avviso c’è anche un caso per estendere Thread, infatti lo avete dimostrato nel vostro codice.

    Se si implementa Runnable, la class che implementa Runnable non ha alcun controllo sul nome del thread, è il codice chiamante che può impostare il nome del thread, in questo modo:

     new Thread(myRunnable,"WhateverNameiFeelLike"); 

    ma se estendi il thread, puoi gestirlo all’interno della class stessa (proprio come nel tuo esempio, tu chiami il thread ‘ThreadB’). In questo caso tu:

    A) potrebbe dargli un nome più utile ai fini del debug

    B) stanno forzando che quel nome sia usato per tutte le istanze di quella class (a meno che non si ignori il fatto che si tratta di un thread e si fa sopra con esso come se fosse un Runnable ma stiamo parlando di convenzione qui in ogni caso così può ignora questa possibilità che sento).

    Ad esempio, potresti anche prendere una traccia dello stack della sua creazione e usarla come nome del thread. Questo potrebbe sembrare strano ma, a seconda di come è strutturato il tuo codice, può essere molto utile ai fini del debug.

    Potrebbe sembrare una cosa piccola, ma in cui hai un’applicazione molto complessa con molti thread e all’improvviso le cose “si sono fermate” (sia per motivi di deadlock o forse a causa di un difetto in un protocollo di rete che sarebbe meno ovvio – o altri motivi infiniti) quindi ottenere uno stack dump da Java dove tutti i thread sono chiamati ‘Thread-1’, ‘Thread-2’, ‘Thread-3’ non è sempre molto utile (dipende da come i thread sono strutturato e se è ansible dire utilmente quale è solo tramite la loro traccia di stack – non sempre è ansible se si utilizzano gruppi di più thread che eseguono tutti lo stesso codice).

    Detto questo, puoi anche fare quanto sopra in un modo generico creando un’estensione della class thread che imposta il suo nome su una traccia stack della sua chiamata di creazione e poi usala con le tue implementazioni Runnable invece della class standard java Thread (vedi sotto) ma oltre alla traccia dello stack potrebbero esserci più informazioni specifiche del contesto che sarebbero utili nel nome del thread per il debug (un riferimento a una delle molte code o socket che potrebbe processare per esempio nel qual caso potresti preferire estendi Thread specificatamente per quel caso in modo che tu possa fare in modo che il compilatore ti obblighi (o altri che usano le tue librerie) a passare in determinate informazioni (es. la coda / socket in questione) per l’uso nel nome).

    Ecco un esempio del thread generico con la traccia dello stack chiamante come nome:

     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")); } } 

    ed ecco un esempio dell’output che confronta i due nomi:

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

    Dato che questo è un argomento molto popolare e le buone risposte sono distribuite dappertutto e trattate in modo approfondito, ho sentito che è giustificabile compilare le buone risposte degli altri in una forma più concisa, così i principianti hanno una facile panoramica in anticipo:

    1. Solitamente estendi una class per aggiungere o modificare funzionalità. Quindi, se non vuoi sovrascrivere alcun comportamento del Thread , usa Runnable.

    2. Nella stessa ottica, se non è necessario ereditare i metodi di thread, è ansible fare a meno di tale overhead utilizzando Runnable.

    3. Single inheritance : se estendi Thread non puoi estendere da nessun’altra class, quindi se è quello che devi fare, devi usare Runnable.

    4. È buona norma separare la logica di dominio da mezzi tecnici, in questo senso è meglio avere un’attività eseguibile che isola l’ attività dal runner .

    5. È ansible eseguire lo stesso object Runnable più volte , tuttavia un object Thread può essere avviato solo una volta. (Forse il motivo, perché gli esecutori accettano i Runnable, ma non i Thread.)

    6. Se sviluppi il tuo compito come Runnable, hai tutta la flessibilità su come usarlo ora e in futuro . Puoi farlo funzionare contemporaneamente tramite Executor ma anche tramite Thread. E puoi ancora usarlo / chiamarlo non simultaneamente all’interno della stessa discussione, proprio come qualsiasi altro tipo / object ordinario.

    7. Ciò semplifica anche la separazione degli aspetti della logica delle attività e della concorrenza nei test delle unità .

    8. If you are interested in this question, you might be also interested in the difference between Callable and Runnable .

    This is discussed in Oracle’s Defining and Starting a Thread tutorial:

    Which of these idioms should you use? The first idiom, which employs a Runnable object, is more general, because the Runnable object can subclass a class other than Thread. The second idiom is easier to use in simple applications, but is limited by the fact that your task class must be a descendant of Thread. This lesson focuses on the first approach, which separates the Runnable task from the Thread object that executes the task. Not only is this approach more flexible, but it is applicable to the high-level thread management APIs covered later.

    In other words, implementing Runnable will work in scenarios where your class extends a class other than Thread . Java does not support multiple inheritance. Also, extending Thread will not be possible when using some of the high-level thread management APIs. The only scenario where extending Thread is preferable is in a small application that won’t be subject to updates in future. It is almost always better to implement Runnable as it is more flexible as your project grows. A design change won’t have a major impact as you can implement many interfaces in java, but only extend one class.

    If I am not wrong, it’s more or less similar to

    Qual è la differenza tra un’interfaccia e una class astratta?

    extends establishes ” Is A ” relation & interface provides ” Has a ” capability.

    Prefer implements Runnable :

    1. If you don’t have to extend Thread class and modify Thread API default implementation
    2. If you are executing a fire and forget command
    3. If You are already extending another class

    Prefer ” extends Thread ” :

    1. If you have to override any of these Thread methods as listed in oracle documentation page

    Generally you don’t need to override Thread behaviour. So implements Runnable is preferred for most of the times.

    On a different note, using advanced ExecutorService or ThreadPoolExecutorService API provides more flexibility and control.

    Have a look at this SE Question:

    ExecutorService vs Casual Thread Spawner

    Difference between Extending Thread and Implementing Runnable are:

    inserisci la descrizione dell'immagine qui

    Separating the Thread class from the Runnable implementation also avoids potential synchronization problems between the thread and the run() method. A separate Runnable generally gives greater flexibility in the way that runnable code is referenced and executed.

    One reason you’d want to implement an interface rather than extend a base class is that you are already extending some other class. You can only extend one class, but you can implement any number of interfaces.

    If you extend Thread, you’re basically preventing your logic to be executed by any other thread than ‘this’. If you only want some thread to execute your logic, it’s better to just implement Runnable.

    if you use runnable you can save the space to extend to any of your other class.

    Can we re-visit the basic reason we wanted our class to behave as a Thread ? There is no reason at all, we just wanted to execute a task, most likely in an asynchronous mode, which precisely means that the execution of the task must branch from our main thread and the main thread if finishes early, may or may not wait for the branched path(task).

    If this is the whole purpose, then where do I see the need of a specialized Thread. This can be accomplished by picking up a RAW Thread from the System’s Thread Pool and assigning it our task (may be an instance of our class) and that is it.

    So let us obey the OOPs concept and write a class of the type we need. There are many ways to do things, doing it in the right way matters.

    We need a task, so write a task definition which can be run on a Thread. So use Runnable.

    Always remember implements is specially used to impart a behaviour and extends is used to impart a feature/property.

    We do not want the thread’s property, instead we want our class to behave as a task which can be run.

    Yes, If you call ThreadA call , then not need to call the start method and run method is call after call the ThreadA class only. But If use the ThreadB call then need to necessary the start thread for call run method. If you have any more help, reply me.

    I find it is most useful to use Runnable for all the reasons mentioned, but sometimes I like to extend Thread so I can create my own thread stopping method and call it directly on the thread I have created.

    Java does not support multiple inheritence so if you extends Thread class then no other class will be extended.

    For Example: If you create an applet then it must extends Applet class so here the only way to create thread is by implementing Runnable interface

    That’s the S of SOLID : Single responsibility.

    A thread embodies the running context (as in execution context: stack frame, thread id, etc.) of the asynchronous execution of a piece of code. That piece of code ideally should be the same implementation, whether synchronous or asynchronous .

    If you bundle them together in one implementation, you give the resulting object two unrelated causes of change:

    1. thread handling in your application (ie. querying and modifying the execution context)
    2. algorithm implemented by the piece of code (the runnable part)

    If the language you use supports partial classs or multiple inheritance, then you can segregate each cause in its own super class, but it boils down to the same as composing the two objects, since their feature sets don’t overlap. That’s for the theory.

    In practice, generally speaking, a programme does not need to carry more complexity than necessary. If you have one thread working on a specific task, without ever changing that task, there is probably no point in making the tasks separate classs, and your code remains simpler.

    In the context of Java , since the facility is already there , it is probably easier to start directly with stand alone Runnable classs, and pass their instances to Thread (or Executor ) instances. Once used to that pattern, it is not harder to use (or even read) than the simple runnable thread case.

    Difference between Thread and runnable .If we are creating Thread using Thread class then Number of thread equal to number of object we created . If we are creating thread by implementing the runnable interface then we can use single object for creating multiple thread.So single object is shared by multiple Thread.So it will take less memory

    So depending upon the requirement if our data is not senstive. So It can be shared between multiple Thread we can used Runnable interface.

    Adding my two cents here – Always whenever possible use implements Runnable . Below are two caveats on why you should not use extends Thread s

    1. Ideally you should never extend the Thread class; the Thread class should be made final . At least its methods like thread.getId() . See this discussion for a bug related to extending Thread s.

    2. Those who like to solve puzzles can see another side effect of extending Thread. The below code will print unreachable code when nobody is notifying them.

    Please see 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 "); } } } 

    One difference between implementing Runnable and extending Thread is that 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.

    A class that implements Runnable is not a thread and just a class. For a Runnable to be executed by a Thread, you need to create an instance of Thread and pass the Runnable instance in as the target.

    In most cases, the Runnable interface should be used if you are only planning to override the run() method and no other Thread methods. This is important because classs should not be subclassd unless the programmer intends on modifying or enhancing the fundamental behavior of the class.

    When there is a need to extend a superclass, implementing the Runnable interface is more appropriate than using the Thread class. Because we can extend another class while implementing Runnable interface to make a thread. But if we just extend the Thread class we can’t inherit from any other class.