2345 votes

"implements Runnable" vs "extends Thread"

À partir de ce moment que j'ai passé avec les threads en Java, j'ai trouvé ces deux façons d'écrire des threads.

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


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

Est-il une différence significative dans ces deux blocs de code?

1820voto

Jon Skeet Points 692016

Oui: implémente Runnable est la meilleure façon de le faire, de l'OMI. Vous n'êtes pas vraiment spécialisé le fil de comportement. Vous êtes juste de donner quelque chose à exécuter. Cela signifie que la composition est la philosophiquement plus "purs" de chemin à faire.

En pratique , il signifie que vous pouvez mettre en oeuvre Runnable et de prolonger d'une autre classe.

623voto

Bob Cross Points 13552

tl;dr: implements Runnable est mieux. Cependant, la mise en garde est importante

En général, je vous conseille d'utiliser quelque chose comme Runnable plutôt que d' Thread , car il vous permet de garder votre travail faiblement couplé avec votre choix de simultanéité. Par exemple, si vous utilisez un Runnable et décider plus tard que ce n'est pas en fait besoin de sa propre Thread, vous pouvez les appeler threadA.run().

Mise en garde: ici, je déconseille vivement l'utilisation de matières premières de Threads. Je préfère de beaucoup l'utilisation de Callables et FutureTasks (à Partir de la javadoc: "Un résiliable calcul asynchrone"). L'intégration de délais d'attente, bon l'annulation et à la mise en pool de threads de la moderne de la simultanéité de soutien sont tous beaucoup plus utile pour moi que des tas de brutes Threads.

Suivi: il est FutureTask constructeur qui vous permet d'utiliser Runnables (si c'est ce que vous êtes plus à l'aise avec) et même le bénéfice du moderne, de la simultanéité des outils. Pour citer la javadoc:

Si vous n'avez pas besoin d'un résultat en particulier, envisager d'utiliser des constructions de la forme:

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

Donc, si l'on remplace leur runnable votre threadA, nous obtenons les suivantes:

new FutureTask<Object>(threadA, null)

Une autre option qui vous permet de rester plus près de la Runnables est un ThreadPoolExecutor. Vous pouvez utiliser l' exécution de la méthode à passer dans un Exécutable à 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 deviendrait quelque chose comme ce qui suit (à l'aide de l' Exécuteur.newCachedThreadPool() de l'usine méthode):

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

292voto

panzerschreck Points 1163

Morale de l'histoire : Hériter uniquement si vous souhaitez remplacer un comportement.

ou plutôt il doit être lu comme "Hériter à moins, interface plus"

267voto

Rupesh Yadav Points 2721

Ainsi donc, beaucoup de bonnes Réponses, je tiens à ajouter de plus sur cette, Cela vous aidera à comprendre Extending v/s Implementing Thread_
S'étend lie les deux fichiers de classe de très près et peut causer certains assez difficile de traiter avec code.

Les deux approches font le même travail, mais il y a eu quelques différences.
La plus courante différence est

  1. Lorsque vous étend la classe Thread, après que vous ne pouvez pas étendre une autre classe dont vous aurez besoin. (Comme vous le savez, Java ne permet pas d'hériter de plus d'une catégorie).
  2. Lorsque vous implements Runnable, vous pouvez économiser de l'espace pour votre classe d'étendre à toute autre catégorie dans le futur ou présent.

Toutefois, une 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 permet de comprendre plus clearly_

//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 de l'interface Runnable, une seule instance d'une classe est en cours de création et il a été partagé par les différents threads. Si la valeur du compteur est incrémenté pour chaque thread d'accès.

Alors que, de la classe Thread approche, vous devez avoir à créer instance distincte pour chaque thread d'accès. Donc différente de la mémoire est allouée pour chaque classe d'instances et chacune a sa propre compteur, la valeur reste la même, ce qui signifie pas d'incrément va se passer parce que aucun de la référence de l'objet est le même.

Quand utiliser l'Exécutable?
Utilisation de l'interface Runnable lorsque vous souhaitez accéder à la même ressource du groupe de threads. Évitez d'utiliser des classe Thread ici, parce que de multiples objets de la création consomme plus de mémoire et il devient une grosse surcharge de performance.

A class that implements Runnable is not a thread and just a class. For a Runnable to become a Thread, You need to create an instance of Thread and passing itself in as the target.

Dans la plupart des cas, l'interface Runnable doit être utilisé si vous êtes planification pour remplacer la méthode run() et aucun autre Thread méthodes. Ceci est important parce que les classes ne doivent pas être sous-classé, à moins que le programmeur a l'intention de modifier ou d'améliorer le comportement fondamental de la classe.

Lorsqu'il est nécessaire d'étendre une super-classe, l'implémentation de l'interface Runnable 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 Runnable de faire un thread.

J'espère que cela va vous aider!

89voto

Herms Points 13069

Une chose que je suis surpris, n'a pas encore été mentionnés, c'est que la mise en œuvre de Runnable rend votre classe plus souple.

Si vous étendez le thread de l'action que vous faites est toujours dans un fil de discussion. Toutefois, si vous étendez Exécutable, il n'a pas à être. Vous pouvez l'exécuter dans un thread, ou de passer à une sorte d'exécuteur testamentaire de service, ou tout simplement passer autour d'une tâche au sein d'un seul thread de l'application (peut-être à être exécuté plus tard, mais dans le même thread). Les options sont beaucoup plus ouverts si vous utilisez seulement Praticable que si vous vous lier à enfiler.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X