"implements Runnable" vs "extends Thread" en Java

D'après le temps que J'ai passé avec les threads en Java, j'ai trouvé ces deux façons d'écrire les threads:

avec implements Runnable :

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

ou, avec extends Thread :

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

y a-t-il une différence significative entre ces deux blocs de code ?

1825
demandé sur Steve Chambers 2009-02-12 17:28:46
la source

30 ответов

Oui: met en œuvre les Runnable est la meilleure façon de le faire, de l'OMI. Vous n'êtes pas vraiment spécialisé dans le comportement du fil. Tu lui donnes juste quelque chose pour courir. Cela signifie composition est le philosophiquement "purer" chemin à parcourir.

en termes" pratiques , cela signifie que vous pouvez mettre en œuvre Runnable et étendre d'une autre classe ainsi.

1466
répondu Jon Skeet 2012-10-23 02:09:24
la source

tl;dr: implements Runnable is better. Toutefois, la mise en garde est importante

en général, je recommande d'utiliser quelque chose comme Runnable plutôt que Thread parce qu'il vous permet de garder votre travail seulement vaguement couplé avec votre choix de concurrence. Par exemple , si vous utilisez un Runnable et décidez plus tard que cela ne nécessite pas en fait son propre Thread , vous pouvez simplement appeler threadA.exécuter.)(

avertissement: ici, je déconseille fortement l'utilisation de fils bruts. Je préfère de loin l'utilisation de appelables et FutureTasks (du javadoc:"un calcul asynchrone annulable"). L'intégration des temps morts, l'annulation correcte et la mise en commun des fils du support de concurrence moderne sont tous beaucoup plus utiles pour moi que des tas de fils bruts.

suivi: il y a un FutureTask constructeur qui vous permet d'utiliser Runnables (si c'est ce que vous êtes le plus à l'aise avec) et encore obtenir l'avantage des outils modernes de concurrence. Pour citer le javadoc:

si vous n'avez pas besoin d'un résultat particulier, envisagez d'utiliser des constructions du formulaire:

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

donc, si nous remplaçons leur runnable par votre threadA , nous obtenons ce qui suit:

new FutureTask<Object>(threadA, null)

une autre option qui vous permet de rester plus près de Runnables est un ThreadPoolExecutor . Vous pouvez utiliser la méthode execute pour passer dans une exécutable pour exécuter "la tâche donnée dans le futur."

si vous voulez essayer d'utiliser un pool de threads, le fragment de code ci-dessus ressemblera à ce qui suit (en utilisant les exécuteurs ).newCachedThreadPool () méthode usine):

ExecutorService es = Executors.newCachedThreadPool();
es.execute(new ThreadA());
500
répondu Bob Cross 2016-06-28 10:26:50
la source

Morale de l'histoire:

héritez seulement si vous voulez passer outre certains comportements.

, Ou plutôt il doit être lu comme suit:

hérite moins, interface plus.

232
répondu panzerschreck 2015-08-28 19:26:50
la source

Eh bien tant de bonnes réponses, je veux ajouter plus sur ce. Cela aidera à comprendre Extending v/s Implementing Thread .

étend lie deux fichiers de classe de très près et peut causer assez difficile à traiter avec le code.

les Deux approches font le même travail, mais il y a eu quelques différences.

la différence la plus courante est

  1. lorsque vous étendez la classe de fil, après que vous ne pouvez étendre aucune autre classe que vous avez demandé. (Comme vous le savez, Java ne permet pas d'hériter plus d'une classe).
  2. lorsque vous implémentez Runnable, vous pouvez économiser de l'espace pour que votre classe étende n'importe quelle autre classe dans le futur ou maintenant.

Cependant, un différence significative entre l'implémentation de Runnable et l'extension de Thread, c'est 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.

l'exemple suivant vous aide à comprendre plus clairement

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

Sortie du programme ci-dessus.

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

dans l'approche interface exécutable, une seule instance d'une classe est créée et elle a été partagée par différents threads. Ainsi, la valeur de counter est incrémentée pour chaque accès thread.

Attendu Que, Fil approche de classe, vous devez créer une instance séparée pour chaque accès thread. Par conséquent, une mémoire différente est attribuée à chaque instance de classe et chacune a un compteur séparé, la valeur reste la même, ce qui signifie qu'aucun incrément ne se produira parce qu'aucune référence d'objet n'est la même.

quand utiliser Runnable?

Utilisez l'interface exécutable lorsque vous voulez accéder à la même ressource à partir du groupe de threads. Éviter D'utiliser du filetage classe ici, parce que la création d'objets multiples consomme plus de mémoire et devient une grosse performance aérienne.

une classe qui implémente Runnable n'est pas un thread et juste une classe. Pour Qu'une exécutable devienne un Thread, vous devez créer une instance de Thread et se passer en tant que cible.

dans la plupart des cas, l'interface Runnable doit être utilisée si vous ne prévoyez de remplacer la méthode run() et aucune autre méthode de Thread. C'est important parce que les classes ne devraient pas être sous-classées à moins que le programmeur n'ait l'intention de modifier ou d'améliorer le comportement fondamental de la classe.

Lorsqu'il est nécessaire d'étendre une superclasse, la mise en œuvre de l'interface exécutable est plus appropriée que l'utilisation de la classe Thread. Parce que nous pouvons étendre une autre classe tout en implémentant l'interface Runnable pour créer un thread.

j'espère que cela aidera!

189
répondu Rupesh Yadav 2016-11-11 13:47:33
la source

une chose qui m'étonne n'a pas encore été mentionnée, c'est que la mise en œuvre de Runnable rend votre classe plus flexible.

si vous étendez le thread, alors l'action que vous faites sera toujours dans un thread. Cependant, si vous mettez en œuvre Runnable il ne doit pas être. Vous pouvez l'exécuter dans un thread, ou le passer à une sorte de service d'exécuteur, ou juste le passer autour comme une tâche dans une application filetée simple (peut-être à exécuter à un moment ultérieur, mais dans le même thread). Les options sont beaucoup plus ouvertes si vous utilisez Runnable que si vous vous liez à Thread .

73
répondu Herms 2016-10-12 15:53:26
la source

si vous voulez implémenter ou étendre une autre classe, alors Runnable interface est préférable."

la différence la plus courante est

enter image description here

quand vous classe extends Thread , après cela vous ne pouvez pas étendre une autre classe que vous avez demandé. (Comme vous le savez, Java ne permet pas d'hériter plus d'une classe).

quand vous implements Runnable , vous pouvez économiser une place pour votre classe pour étendre n'importe quelle autre classe dans le futur ou maintenant.

  • Java ne supporte pas les héritages multiples, ce qui signifie que vous ne pouvez étendre qu'une classe en Java, donc une fois que vous avez étendu la classe Thread, vous avez perdu votre chance et ne pouvez pas étendre ou hériter une autre classe en Java.

  • In Programmation orientée objet étendre une classe signifie généralement ajouter de nouvelles fonctionnalités, modifier ou améliorer les comportements. Si nous ne faisons aucune modification sur Thread, utilisez plutôt L'interface Runnable.

  • interface Runnable représentent une tâche qui peut être exécutée par fil simple ou exécuteurs ou tout autre moyen. ainsi la séparation logique de la tâche comme Runnable que le fil est une bonne décision de conception.

  • séparer la tâche comme exécutable signifie que nous pouvons réutiliser la tâche et a également la liberté de l'exécuter à partir de différents moyens. puisque vous ne pouvez pas redémarrer un Thread une fois terminé. de nouveau Praticable vs Thread pour tâche, Runnable est gagnant.

  • Java designer reconnaît ceci et c'est pourquoi les exécuteurs acceptent les tâches exécutables et ils ont worker thread qui exécute ces tâches.

  • hériter de tous les fils les méthodes sont des overhead supplémentaires juste pour représenter une tâche qui peut être fait facilement avec Runnable.

gracieuseté de javarevisited.blogspot.com

ce sont quelques-unes des différences notables entre Thread et Runnable en Java, si vous connaissez d'autres différences sur Thread vs Runnable que s'il vous plaît le partager via des commentaires. Personnellement, j'utilise Lançable sur les filetages pour ce scénario et recommande d'utiliser Interface Runnable ou Callable en fonction de vos besoins.

Cependant, la différence significative est.

dans la classe extends Thread , chacun de vos fils crée un objet unique et s'y associe. Lorsque vous implements Runnable , il partage le même objet à plusieurs threads.

66
répondu Nidhish Krishnan 2016-03-21 18:02:55
la source

en fait, il n'est pas sage de comparer Runnable et Thread entre eux.

ces deux-là ont une dépendance et une relation dans multi-threading tout comme Wheel and Engine relation de véhicule à moteur.

je dirais, il n'y a qu'un seul moyen pour multi-threading avec deux étapes. Permettez-moi de faire de mon point de vue.

Praticable:

Lors de la mise en œuvre interface Runnable cela signifie que vous créez quelque chose qui est run able dans un fil différent. Créer maintenant quelque chose qui peut tourner à l'intérieur d'un thread (runnable à l'intérieur d'un thread), ne signifie pas créer un Thread.

Donc la classe MyRunnable n'est rien d'autre qu'une classe ordinaire avec une méthode void run . Et ses objets seront des objets ordinaires avec seulement une méthode run qui s'exécutera normalement lorsqu'on l'appelle. (sauf si nous passons l'objet dans un thread).

Thread:

class Thread , je dirais une classe très spéciale avec la possibilité de démarrer un nouveau Thread qui permet en fait le multi-threading à travers sa méthode start() .

pourquoi ne pas comparer?

Parce que nous avons besoin des deux pour le multi-threading.

pour multi-filetage nous avons besoin de deux choses:

  • quelque chose qui peut fonctionner à l'intérieur d'un Thread (Runnable).
  • quelque chose qui peut démarrer un nouveau Thread (Thread).

donc techniquement et théoriquement les deux sont nécessaires pour démarrer un fil, on va courir et on va faire courir (comme "1519270920 Wheel and Engine de véhicule à moteur).

C'est pourquoi vous ne pouvez pas démarrer une thread avec MyRunnable vous devez le passer à une instance de Thread .

mais il est possible de créer et exécuter un thread seulement en utilisant class Thread parce que la classe Thread met en œuvre Runnable donc nous savons tous Thread est également un Runnable à l'intérieur.

enfin Thread et Runnable sont complémentaires les uns des autres pour la multi-position et non pas de concurrence ou de remplacement.

61
répondu Saif 2016-08-03 08:58:59
la source

vous devriez implémenter Runnable, mais si vous utilisez Java 5 ou plus, vous ne devriez pas le démarrer avec new Thread mais utiliser un ExecutorService à la place. Pour plus de détails, voir: comment implémenter un threading simple en Java .

41
répondu Fabian Steeg 2017-05-23 15:26:36
la source

Je ne suis pas un expert, mais je peux penser à une raison pour mettre en œuvre Runnable au lieu de prolonger le Thread: Java ne supporte qu'un seul héritage, donc vous ne pouvez étendre qu'une seule classe.

éditer: cela dit à l'origine "la mise en œuvre d'une interface nécessite moins de ressources."aussi bien, mais vous devez créer une nouvelle instance de Thread de toute façon, donc c'était mal.

31
répondu Powerlord 2009-02-12 17:32:01
la source

je dirais qu'il y a une troisième voie:

public class Something {

    public void justAnotherMethod() { ... }

}

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

peut-être que ceci est influencé un peu par mon usage récent de Javascript et Actionscript 3, mais de cette façon votre classe n'a pas besoin d'implémenter une interface assez vague comme Runnable .

19
répondu Bart van Heukelom 2010-10-26 01:41:00
la source

avec la sortie de Java 8, Il y a maintenant une troisième option.

Runnable est une interface fonctionnelle , ce qui signifie que des instances de celui-ci peuvent être créés avec des expressions lambda ou des références de méthode.

Votre exemple peut être remplacé par:

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

ou si vous voulez utiliser un ExecutorService et une référence de méthode:

executor.execute(runner::run)

ce ne sont pas seulement beaucoup plus court que vos exemples, mais vient aussi avec beaucoup des avantages énoncés dans d'autres réponses d'utiliser Runnable sur Thread , comme la responsabilité unique et l'utilisation de la composition parce que vous n'êtes pas spécialisé le comportement du fil. Cette façon évite également de créer une classe supplémentaire si tout ce dont vous avez besoin est un Runnable comme vous le faites dans vos exemples.

16
répondu Alex 2015-09-05 15:10:44
la source

instancier une interface donne une séparation plus claire entre votre code et l'implémentation de threads, donc je préférerais implémenter Runnable dans ce cas.

15
répondu starblue 2009-02-12 17:33:09
la source
  1. Java ne supporte pas les héritages multiples, ce qui signifie que vous ne pouvez étendre qu'une classe en Java, donc une fois que vous avez étendu la classe Thread vous avez perdu votre chance et ne pouvez pas étendre ou hériter une autre classe en Java.
  2. dans la programmation orientée objet étendre une classe signifie généralement ajouter de nouvelles fonctionnalités, modifier ou améliorer les comportements. Si nous ne faisons aucune modification sur Thread que d'utiliser Runnable interface à la place.
  3. Runnable interface représente un Task qui peut être exécuté par Thread ou Executors ou par tout autre moyen. Ainsi, la séparation logique de Task en Runnable par rapport à Thread est une bonne décision de conception.
  4. séparer la tâche comme Runnable signifie que nous pouvons réutiliser la tâche et a également la liberté de l'exécuter de différents moyens. Puisque vous ne pouvez pas redémarrer un Thread une fois qu'il complète, encore une fois Runnable vs Thread pour tâche, Runnable est gagnant.
  5. Java designer reconnaît ceci et c'est pourquoi Executors accepte Runnable comme Task et ils ont worker thread qui exécute ces tâches.
  6. hériter toutes les méthodes Thread sont des frais généraux supplémentaires juste pour représenter un Task qui peut être fait facilement avec Runnable .
12
répondu Hutashan Chandrakar 2017-11-21 18:45:57
la source

Praticable parce que:

  • laisse plus de flexibilité pour le Mise en œuvre exécutable pour étendre une autre classe
  • sépare le code de exécution
  • vous Permet d'exécuter vos exécutable à partir d'un Pool de Threads, le événement de fil, ou de toute autre manière dans avenir.

Même si vous n'avez pas besoin de tout cela maintenant, vous pouvez à l'avenir. Puisqu'il n'y a aucun avantage à passer le fil, Praticable est une meilleure solution.

10
répondu n13 2010-05-07 08:28:57
la source

tout le monde ici semble penser que la mise en œuvre de Runnable est la voie à suivre et je ne suis pas vraiment en désaccord avec eux, mais il ya aussi un cas pour étendre fil à mon avis, en fait, vous avez en quelque sorte démontré dans votre code.

si vous implémentez Runnable alors la classe qui implémente Runnable n'a aucun contrôle sur le nom du thread, c'est le code d'appel qui peut définir le nom du thread, comme ceci:

new Thread(myRunnable,"WhateverNameiFeelLike");

mais si vous prolongez Thread ensuite vous pouvez gérer cela dans la classe elle-même (comme dans votre exemple vous nommez le thread 'ThreadB'). Dans ce cas vous:

a) pourrait lui donner un nom plus utile à des fins de débogage

B) forcent que ce nom soit utilisé pour toutes les instances de cette classe (sauf si vous ignorez le fait qu'il s'agit d'un thread et faites comme si c'était un Runnable mais nous parlons de convention ici dans tous les cas donc peut ignorer que possibilité que je ressens).

vous pourriez même par exemple prendre une trace de sa création et l'utiliser comme nom de thread. Cela peut sembler étrange, mais selon la structure de votre code, cela peut être très utile pour le débogage.

cela peut sembler une petite chose, mais où vous avez une application très complexe avec beaucoup de fils et tout d'un coup les choses "se sont arrêtés" (soit pour des raisons d'impasse ou peut-être à cause d'une faille dans un le protocole de réseau qui serait moins évident - ou d'autres raisons sans fin) alors obtenir un dump de pile de Java où tous les threads sont appelés 'Thread-1','Thread-2','Thread-3' n'est pas toujours très utile (cela dépend de la façon dont vos threads sont structurés et si vous pouvez utilement dire qui est qui juste par leur trace de pile - pas toujours possible si vous utilisez des groupes de threads multiples tous en cours d'exécution du même code).

ayant dit que vous pourriez bien sûr aussi faire le ci-dessus d'une manière générique en créant une extension de la classe thread qui définit son nom à une trace de pile de son appel de création, puis l'utiliser avec vos implémentations exécutables au lieu de la classe de Thread java standard (voir ci-dessous) mais en plus de la trace de pile il pourrait y avoir des informations spécifiques au contexte qui seraient utiles dans le nom de thread pour le débogage (une référence à l'une des nombreuses queues ou sockets qu'il pourrait traiter par exemple dans quel cas vous pourriez préférer étendre le Thread spécifiquement pour ce cas afin que vous puissiez avoir le compilateur vous forcer (ou d'autres utilisateurs de vos bibliothèques) à passer dans certaines informations (par exemple la file/socket en question) pour les utiliser dans le nom).

voici un exemple du fil générique avec la trace de la pile d'appel comme nom:

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

et voici un échantillon de la sortie comparant les deux noms:

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
répondu AntonyM 2012-06-20 03:12:49
la source

Puisqu'il s'agit d'un sujet très populaire et que les bonnes réponses sont éparpillées et traitées en profondeur, j'ai pensé qu'il était justifiable de compiler les bonnes réponses des autres dans une forme plus concise, de sorte que les nouveaux arrivants ont un aperçu facile à l'avance:

  1. vous étendez habituellement une classe pour ajouter ou modifier des fonctionnalités. Donc, si vous ne voulez pas à overwrite any comportement du fil , puis utilisez Runnable.

  2. dans la même lumière, si vous n'avez pas besoin à hériter méthodes de fil, vous pouvez faire sans que au-dessus en utilisant Runnable.

  3. l'héritage Simple : Si vous étendez Fil, vous ne peut pas s'étendre à partir d'une autre classe, donc si c'est ce que vous devez faire, vous devez utiliser Praticable.

  4. c'est une bonne conception de séparer la logique du domaine des moyens techniques, en ce sens, il est préférable d'avoir une tâche exécutable isoler votre tâche de votre runner .

  5. Vous pouvez exécuter la même Praticable objet à plusieurs reprises , un objet Thread, cependant, ne peut être a commencé une fois. (Peut-être la raison, pourquoi les exécuteurs acceptent les exécutables, mais pas les Threads.)

  6. Si vous développez votre tâche Exécutable, vous avez toute souplesse comment l'utiliser maintenant et dans l'avenir . Vous pouvez le faire tourner simultanément via Executors mais aussi via Thread. Et vous pouvez encore l'utiliser / l'appeler non-concurremment dans le même thread comme n'importe quel autre type/objet ordinaire.

  7. cela rend également plus facile de séparer logique des tâches et simultanéité aspects dans votre essais unitaires .

  8. si vous êtes intéressé par cette question, vous pourriez également être intéressé par la différence entre appelable et Runnable .

10
répondu Jörg 2017-05-23 15:26:36
la source

Ceci est discuté dans D'Oracle définissant et démarrant un Thread tutoriel:

lequel de ces idiomes devez-vous utiliser? Le premier idiome, qui emploie un L'objet praticable, est plus général, parce que l'objet Praticable peut sous-classe a Classe autre que Thread. La deuxième idiome est plus facile à utiliser dans les applications simples, mais est limité par le fait que votre tâche la classe doit être un descendant de Fil. Cette leçon se concentre sur première approche, qui sépare la tâche exécutable de l'objet Thread que l'exécution de la tâche. Non seulement cette approche est plus souple, mais il est applicable aux API de gestion de thread de haut niveau couvertes tard.

en d'autres termes, la mise en œuvre de Runnable fonctionnera dans les scénarios où votre classe étend une classe autre que Thread . Java ne supporte pas les héritages multiples. En outre, l'extension Thread ne sera pas possible lorsque utilisation de certaines API de gestion de thread de haut niveau. Le seul scénario où l'extension Thread est préférable est dans une petite application qui ne sera pas sujette à des mises à jour à l'avenir. Il est presque toujours préférable de mettre en œuvre Runnable car il est plus flexible que votre projet se développe. Un changement de conception n'aura pas d'impact majeur car vous pouvez implémenter de nombreuses interfaces en java, mais étendre seulement une classe.

8
répondu Sionnach733 2014-01-21 20:44:09
la source

si je n'ai pas tort, c'est plus ou moins similaire à

Quelle est la différence entre une classe d'interface et une classe abstraite?

s'étend établit " Est Un "rapport & interface fournit" A une " capacité.

Prefer implements Runnable :

  1. si vous ne pas avoir à étendre la classe Thread et modifier la mise en œuvre par défaut de L'API Thread
  2. si vous exécutez une commande fire and forget
  3. si vous étendez déjà une autre classe

Prefer " extends Thread " :

  1. si vous devez outrepasser l'une de ces méthodes Thread comme indiqué dans oracle page de documentation

généralement, vous n'avez pas besoin de modifier le comportement du Thread. Ainsi, metals Runnable est préféré la plupart du temps.

sur une note différente, en utilisant l'API avancée ExecutorService ou ThreadPoolExecutorService offre plus de flexibilité et de contrôle.

Avoir un coup d'oeil à cette SE a la Question:

ExecutorService vs Casual Thread Spawner

6
répondu Ravindra babu 2017-05-23 14:47:31
la source

différence entre L'extension du Thread et la mise en œuvre Runnable sont:

enter image description here

6
répondu Raman Gupta 2017-10-01 18:05:06
la source

séparer la classe Thread de l'implémentation Runnable évite également les problèmes de synchronisation potentiels entre le thread et la méthode run (). Un exécutable séparé donne généralement une plus grande flexibilité dans la façon dont le code exécutable est référencé et exécuté.

5
répondu Govula Srinivas 2010-03-08 10:03:06
la source

une des raisons pour lesquelles vous voulez implémenter une interface plutôt que d'étendre une classe de base est que vous étendez déjà une autre classe. Vous ne pouvez étendre qu'une classe, mais vous pouvez implémenter n'importe quel nombre d'interfaces.

si vous étendez le Thread, vous empêchez fondamentalement votre logique d'être exécutée par un autre thread que 'ceci'. Si vous voulez seulement quelque "fil pour exécuter votre logique, il est préférable d'implémenter simplement Runnable.

5
répondu Nikhil A A 2013-07-25 21:29:00
la source

si vous utilisez runnable vous pouvez économiser l'espace pour étendre à l'une de vos autres classes.

5
répondu user2771655 2013-09-26 09:58:02
la source

pouvons-nous revisiter la raison fondamentale pour laquelle nous voulions que notre classe se comporte comme un Thread ? Il n'y a aucune raison du tout, nous voulions juste exécuter une tâche, très probablement en mode asynchrone, ce qui signifie précisément que l'exécution de la tâche doit se ramifier à partir de notre fil principal et le fil principal si se termine tôt, peut ou ne peut pas attendre le chemin ramifié(tâche).

si c'est le but, alors où puis-je voir le besoin d'un fil spécialisé. Cela peut être réalisé en récupérant un Thread brut de la réserve de threads du système et en lui assignant notre tâche (peut-être une instance de notre classe) et c'est tout.

alors obéissons au concept OOPs et écrivons une classe du type dont nous avons besoin. Il y a plusieurs façons de faire les choses, de les faire de la bonne façon.

nous avons besoin d'une tâche, alors écrivez une définition de tâche qui peut être exécutée sur un Thread. Donc, utiliser l'Exécutable.

rappelez-vous toujours implements est spécialement utilisé pour transmettre un comportement et extends est utilisé pour transmettre une caractéristique/propriété.

nous ne voulons pas de la propriété du thread, nous voulons plutôt que notre classe se comporte comme une tâche qui peut être exécutée.

5
répondu dharam 2013-11-22 07:11:51
la source

Oui, Si vous appelez ThreadA call, alors pas besoin d'appeler la méthode start et la méthode run est call après call la classe ThreadA seulement. Mais si vous utilisez L'appel ThreadB, alors vous devez avoir besoin du thread de départ pour la méthode d'exécution de l'appel. Si vous avez plus de les aider, de me répondre.

4
répondu Manoj Kumar 2012-01-28 12:31:16
la source

je trouve qu'il est très utile d'utiliser Runnable pour toutes les raisons mentionnées, mais parfois j'aime étendre le Thread pour que je puisse créer ma propre méthode d'arrêt du thread et l'appeler directement sur le thread que j'ai créé.

4
répondu Tarvaris Jackson 2012-06-09 23:09:15
la source

Java ne supporte pas les héritages multiples donc si vous étendez la classe Thread alors aucune autre classe ne sera étendue.

par exemple: si vous créez un applet alors il doit étendre la classe Applet donc ici la seule façon de créer le thread est en implémentant l'interface exécutable

4
répondu Himanshu Mohta 2012-06-09 23:28:31
la source

C'est le S de solide : Responsabilité Unique.

Un thread incarne la running contexte (comme dans le contexte d'exécution: la trame de pile, l'id de thread, etc.) de la asynchrone d'un morceau de code. Que morceau de code idéalement devrait être la même mise en œuvre, si synchrone ou asynchrone .

si vous les regroupez en une seule implémentation, vous donnez l'objet résultant deux sans rapport causes de changement:

  1. manipulation du filetage dans votre application (c.-à-d. interrogation et modification du contexte d'exécution)
  2. algorithme implémenté par le morceau de code (la partie exécutable)

si la le langage que vous utilisez supporte les classes partielles ou les héritages multiples, alors vous pouvez séparer chaque cause dans sa propre super classe, mais cela revient à composer les deux objets, puisque leurs ensembles de fonctionnalités ne se chevauchent pas. C'est pour la théorie.

dans la pratique, d'une manière générale, un programme n'a pas besoin d'être plus complexe que nécessaire. Si vous avez un fil travaillant sur une tâche spécifique, sans jamais changer cette tâche, il est probablement inutile de faire les tâches séparent les classes, et votre code reste plus simple.

dans le contexte de Java , puisque la facilité est déjà là , il est probablement plus facile de commencer directement avec stand alone Runnable classes, et passer leurs instances à Thread (ou Executor ) instances. Une fois utilisé à ce modèle, il n'est pas plus difficile à utiliser (ou même à lire) que le cas simple runnable thread.

4
répondu didierc 2013-05-11 12:41:39
la source

différence entre le fil et runnable .Si nous créons le Thread en utilisant la classe Thread alors le nombre de thread égal au nombre d'objet que nous avons créé . Si nous créons du thread en implémentant l'interface exécutable, alors nous pouvons utiliser un seul objet pour créer du thread multiple.Ainsi, un seul objet est partagé par plusieurs Thread.Il faudra donc moins de mémoire

ainsi en fonction de l'exigence si nos données ne sont pas senstive. Donc il peut être partagé entre plusieurs Thread nous peut utiliser l'interface exécutable.

4
répondu Rohit Chugh 2014-03-05 10:13:58
la source

ajoutant mes deux cents ici - toujours autant que possible utiliser implements Runnable . Voici deux mises en garde sur les raisons pour lesquelles vous ne devriez pas utiliser extends Thread s

  1. Idéalement, vous ne devriez jamais étendre la classe de filetage; la classe Thread devrait être faite final . Au moins ses méthodes comme thread.getId() . Voir ce discussion d'un bug lié à l'extension de Thread .

  2. ceux qui aiment résoudre des puzzles peuvent voir un autre effet secondaire de L'extension du fil. Le code ci-dessous imprimera du code inaccessible quand personne ne les avertit.

s'il vous Plaît voir 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
répondu veritas 2015-01-03 12:41:19
la source

une différence entre implémenter Runnable et étendre Thread est qu'en étendant Thread, chacun de vos threads a un objet unique qui lui est associé, alors que implémenter Runnable, beaucoup de threads peuvent partager la même instance objet.

une classe qui implémente Runnable n'est pas un thread et juste une classe. Pour qu'une exécutable puisse être exécutée par un Thread, vous devez créer une instance de Thread et passer l'instance exécutable en tant que cible.

dans la plupart des cas, l'interface Runnable doit être utilisée si vous ne prévoyez de surcharger que la méthode run() et aucune autre méthode Thread. Ceci est important parce que les classes ne doivent pas être sous-classées à moins que le programmeur n'ait l'intention de modifier ou d'améliorer le comportement fondamental de la classe.

Lorsqu'il est nécessaire d'étendre une superclasse, la mise en œuvre de l'interface exécutable est plus appropriée que l'utilisation de la classe Thread. Parce que nous pouvons étendre une autre classe lors de la mise en œuvre de L'interface exécutable pour faire un thread. Mais si nous prolongeons la classe Thread, nous ne pouvons hériter d'aucune autre classe.

4
répondu Vishal 2015-07-03 16:46:02
la source