“implements Runnable” vs “extends Thread” en Java
À partir de ce moment que j'ai passé avec les threads en Java, j'ai trouvé ces deux façons d'écrire des 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
Est-il une différence significative dans ces deux blocs de code ?
- Merci pour cette question, les réponses éclairci beaucoup d'idées fausses que j'ai eu. J'ai regardé dans la façon correcte de faire les threads Java avant, DONC existé et il y a beaucoup de désinformation/obsolète l'information.
- il y a une raison, vous pourriez vouloir étendre Thread (mais je ne le recommande pas), vous pouvez gérer préventivement
interrupt()
. Encore une fois, c'est une idée, il pourrait être utile dans le cas, toutefois je ne le recommande pas. - Veuillez voir aussi la réponse, bien expliqué: stackoverflow.com/q/5562720/285594
- Je suis en train de puzzle ce que vous vouliez dire sur la gestion de l'interruption(). Êtes-vous essayer de remplacer la méthode?
- oui bob. Java n'est que naturellement pour
java.nio.channels.InterruptibleChannel
(s), Vous pouvez jeter un oeil à l'impl. de Fil.interrupt(). À l'aide d'un coup de main de lainterrupt()
de l'appelant est une idée et une approche utile, encore une fois pas recommandé pour les débutants. - il y a un autre moyen de le faire, en étendant
java.nio.channels.spi.AbstractSelector
et remplacerwakeup()
mais c'est une façon trop sale pour évaluer le cas 🙂 - oui.Comme par le code de la classe Thread peut étendre une classe tandis que la classe Thread B cant étendre une autre classe
- Devrait ressembler à la mise en œuvre d'un Rappel plus fonctionnel maintenant.
- cela dépend. Rappel que si vous avez besoin d'un rappel. C'est, si le code en cours d'exécution (le
Runnable
à l'OP) doit exécuter la logique en l'appelant. - dois-je laisser le vide? lors de l'utilisation de fonctions-ils aller sur un autre fil?
- La Composition est préféré au cours de l'Héritage dans la conception orientée Objet
- Ne pas utiliser de filetage directement, vous devez utiliser ExecutorService, qui peut être raillé pour de meilleurs tests
- Étendre Fil lorsque vous avez besoin de CHANGER la façon de Fil se comporte. Mettre en œuvre praticable si vous avez besoin de prolonger un thread différent. Si vous avez besoin de partager un objet entre les threads, Praticable est la façon de le faire, que la thread de ne pas l'autoriser. Si aucun des deux cas s'appliquent, Runnable est plus correct sémantiquement parlant, bien que ce dernier point n'est pas très important, quelqu'un pense que vous avez changé le comportement de fil si vous le prolonger alors que vous ne l'êtes pas.
Vous devez vous connecter pour publier un commentaire.
Oui: met en œuvre
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 composition est le philosophiquement plus "purs" de chemin à parcourir.Dans pratique termes, cela signifie que vous pouvez mettre en œuvre
Runnable
et de l'étendre à partir d'une autre catégorie.if (numberCores > 4) myExecutor.excute(myRunnable); else myRunnable.run()
extends Thread
et si vous ne voulez pas de filetage pourquoi voudriez-vous même de mettre en œuvreRunnable
...Runnable
est, vraiment, une encapsulation de n'importe quel morceau de code. Dans certaines circonstances, il peut être utile d'exécuter unRunnable
même lorsqu'il n'est pas dans le contexte d'un nouveau thread.Thread
seulement à mettre en œuvreRunnable
... heck, vous pouvez passer unThread
exemple, le constructeur de l'autreThread
instance. Cela ne veut pas dire que c'est une bonne idée.Runnable
? Vous mettre en œuvreRunnable
si vous voulez représenter "quelque chose qui peut être exécuté" - il ne doit pas nécessairement être dans un nouveau thread._
, et que les deuxstart()
et_start()
est vraiment déroutant... comme le fait d'avoir une méthode d'instance appelée_sleep()
, quand il y a un statiquesleep
méthode. Non pas que votre_sleep
méthode réellement t n'importe quoi avec l'instance de toute façon. En général, cela ressemble à une mauvaise idée pour moi jusqu'à présent.Thread
tout pour remplacerRunnable
, vous avez à changer les comportements qui ne fait pas partie deThread
lui-même.Thread
implémenteRunnable
, mais c'était une erreur de conception de l'OMI.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 queThread
car il vous permet de garder votre travail faiblement couplé avec votre choix de simultanéité. Par exemple, si vous utilisez unRunnable
et décider plus tard que ce n'est pas en fait besoin de son propreThread
, vous pouvez les appeler threadA.run().Mise en garde: Autour d'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 y a un
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:
Donc, si l'on remplace leur
runnable
avec votrethreadA
, nous obtenons les suivantes:Une autre option qui vous permet de rester plus près de la Runnables est un ThreadPoolExecutor. Vous pouvez utiliser le exécuter méthode pour 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 la Les exécuteurs.newCachedThreadPool() méthode de fabrique):
es
serait mieux comme un statique (ou d'injection) champ donc il est créé une fois.FutureTask
directement est généralement pas ce que vous voulez faire.ExecutorService
de la volonté de créer lesFuture
pour vous lorsque voussubmit
unRunnable
/Callable
à eux. De même pourScheduledExecutorService
s etScheduledFuture
lorsque vousschedule
unRunnable
/Callable
.Morale de l'histoire:
Hériter uniquement si vous souhaitez remplacer un comportement.
Ou plutôt il doit être lu comme suit:
Hériter à moins, interface plus.
run()
méthode.java.lang.Thread
en remplaçant larun()
méthode. Dans ce cas, vous devez remplacer lastart()
méthode je suppose. Normalement, vous réutilisez le comportement de lajava.lang.Thread
par l'injection de l'exécution de votre bloc dans larun()
méthode.Bien, 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.
Les plus courantes différence est
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 aidera à comprendre plus clairement
De sortie du programme ci-dessus.
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, 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 aux mêmes ressources à partir 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.
Une classe qui implémente Runnable n'est pas d'un fil, juste une classe. Pour un Exécutable pour devenir un Fil, Vous devez créer une instance de Thread et en passant lui-même en tant que cible.
Dans la plupart des cas, l'interface Runnable doit être utilisé si vous êtes planification pour remplacer le
run()
méthode 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!
ExtendsThread et = new ExtendsThread();
Thread tc1 = new Thread(et);
tc1.start();
Thread.sleep(1000);
Thread tc2 = new Thread(et);
tc2.start();
Thread.sleep(1000);
Thread tc3 = new Thread(et);
tc3.start();
Est-il plus clair?Thread
incrémentation ainsi, la déclarationby extending Thread, each of your threads has a unique object associated with it, whereas implementing Runnable, many threads can share the same object instance
alors mal? Si non, alors qu'est ce qu'un cas qui illustre cette?+ " hashcode: " + this.hashCode()
Thread
, faire de multiples instances de laThread
deviennent en fait des objets différents? Parce que je pense que c'est faux...new Thread(et)
dans le processus en cours d'exécution je.e (comme vous l'avez dit à juste titre)ExtendsThread et = new ExtendsThread(); Thread tc1 = new Thread(et); tc1.start(); Thread tc2 = new Thread(et); tc1.start();
maintenant ces deux thread partagez le même cas, j'.e<et>
, où, comme dans ce cas de ne pas [s'il vous plaît lire le commentaire ci-dessous pour exécution]ExtendsThread
si vous créez des 3 instances deImplementsRunnable
donc je pense que ce n'est pas un argument valable. Downvoted.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. Cependant, si vous mettez en œuvre
Runnable
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 venez d'utiliserRunnable
que si vous vous lier àThread
.Thread
objet trop parce queThread implements Runnable
... 😉 Mais il "sent de mieux en mieux" à faire ce genre de choses avec unRunnable
que de le faire avec unThread
!Thread
ajoute beaucoup de choses que vous n'avez pas besoin, et dans de nombreux cas ne voulez pas. Vous êtes toujours mieux de la mise en œuvre de l'interface qui correspond à ce que vous êtes en train de faire.Si vous voulez met en œuvre ou s'étend à toute autre classe alors
Runnable
interface est plus préférable, sinon, si vous ne voulez pas que d'autres de la classe de prolonger ou de mettre en œuvre puisThread
classe est préférable.Les plus courantes différence est
Lorsque vous
extends Thread
classe, 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).Lorsque vous
implements Runnable
, vous pouvez économiser de l'espace pour votre classe d'étendre à toute autre catégorie dans le futur ou le présent.Java ne prend pas en charge plusieurs héritages, ce qui signifie que vous ne pouvez étendre une classe en Java donc, une fois que vous avez prolongé classe Thread vous avez perdu votre chance et ne peuvent étendre ou d'en hériter d'une autre classe en Java.
En programmation orientée Objet, l'extension d'une classe signifie généralement, l'ajout de nouvelles fonctionnalités, et de la modification ou de l'amélioration des comportements. Si nous ne sommes pas en faire toute modification sur le Fil puis l'utilisation de l'interface Runnable à la place.
Interface Runnable représente une Tâche qui peut être exécuté par la plaine de Thread ou les Exécuteurs testamentaires ou tout autre moyen. donc logique de séparation de la Tâche Exécutable que de Fil est une bonne décision de conception.
Séparant tâche 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.
Concepteur Java reconnaît cela et c'est pourquoi les Exécuteurs accepter Praticable de la Tâche et ils ont thread qui exécute ces tâches.
Hériter de tous les Threads sont les méthodes de traitement supplémentaire juste pour la représentation d'une Tâche qui peut être fait facilement avec de l'Exécutable.
Courtoisie de la part de javarevisited.blogspot.com
Ce sont quelques-uns des différences notables entre le Fil et Exécutables en Java. Si vous connaissez d'autres différences sur le Thread vs Praticable que s'il vous plaît partager via les commentaires. Personnellement, j'utilise Lançable sur les filetages pour ce scénario et recommande d'utiliser des Exécutables ou Remboursables par anticipation de l'interface en fonction de votre exigence.
Cependant, la différence significative est.
Lorsque vous
extends Thread
classe, chaque thread crée un objet unique et de s'associer avec elle.Lorsque vous
implements Runnable
, il partage le même objet de plusieurs threads.En fait, Il n'est pas sage de comparer
Runnable
etThread
les uns avec les autres.Ce deux ont une dépendance et parenté dans le multi-threading comme
Wheel and Engine
relation de véhicule à moteur.Je dirais, il n'y a qu'une seule manière pour les multi-threading avec deux étapes. Permettez-moi de faire mon point.
Praticable:
Lors de la mise en œuvre de
interface Runnable
cela signifie que vous sont en train de créer quelque chose qui estrun able
dans un thread différent. Maintenant en train de créer quelque chose qui peut s'exécuter à l'intérieur d'un thread (runnable à l'intérieur d'un fil), ne signifie pas la création d'un Thread.Si la classe
MyRunnable
n'est rien mais une classe ordinaire avec unvoid run
méthode.Et c'est les objets à quelques les objets ordinaires avec seulement une méthode
run
qui va s'exécuter normalement, lorsqu'on les appelle. (sauf si on fait passer l'objet dans un thread).Fil:
class Thread
, Je dirais Une classe très spéciale, avec la capacité de commencer un nouveau Thread qui permet réellement multi-threading par le biais de sonstart()
méthode.Pourquoi pas sage de comparer?
Parce que nous avons besoin d'eux pour le multi-threading.
Pour le Multi-threading nous avons besoin de deux choses:
Donc, techniquement et théoriquement les deux d'entre eux est nécessaire pour démarrer un thread, on va exécuter et on va le faire fonctionner (Comme
Wheel and Engine
de véhicule à moteur).C'est pourquoi vous ne pouvez pas démarrer un thread avec
MyRunnable
vous avez besoin de la passer à une instance deThread
.Mais il est possible de créer et d'exécuter un seul thread à l'aide de
class Thread
parce que la ClasseThread
implémenteRunnable
sorte que nous savons tousThread
est aussi unRunnable
à l'intérieur.Enfin
Thread
etRunnable
sont complètent l'une l'autre pour le multithreading pas de concurrent ou d'un remplacement.ThreadA
n'a plus de sensVous devez mettre en œuvre Praticable, mais si vous êtes en cours d'exécution sur Java 5 ou plus, vous ne devriez pas commencer avec
new Thread
mais utiliser un ExecutorService à la place. Pour plus de détails voir: Comment mettre en œuvre simple de thread en Java.Je ne suis pas un expert, mais je pense que l'une des raisons pour mettre en œuvre Exécutable au lieu de prolonger le Fil: Java prend uniquement en charge de l'héritage simple, de sorte que vous ne pouvez étendre une classe.
Edit: Ce d'abord dit "mise en Œuvre d'une interface nécessite moins de ressources." ainsi, mais vous avez besoin de créer un nouveau Thread instance de toute façon, si c'était faux.
Je dirais qu'il y a une troisième voie:
C'est peut-être influencé un peu par ma récente lourde utilisation de Javascript et Actionscript 3, mais de cette façon, votre classe n'a pas besoin de mettre en œuvre une jolie vague de l'interface comme
Runnable
.Avec la sortie de Java 8, il y a maintenant une troisième option.
Runnable
est un interface fonctionnelle, ce qui signifie que les instances de celui-ci peut être créé avec les expressions lambda ou de la méthode de référence.Votre exemple peut être remplacé par:
ou si vous souhaitez utiliser un
ExecutorService
et une méthode de référence:Ce ne sont pas seulement beaucoup plus courte que vos exemples, mais aussi venir avec de nombreux avantages énoncés dans d'autres réponses de l'aide
Runnable
surThread
, tels que la responsabilité unique et à l'aide de la composition, parce que vous n'êtes pas spécialisée le fil de comportement. De cette façon permet également d'éviter la création d'une classe supplémentaire si vous avez besoin d'unRunnable
comme vous le faites dans vos exemples.() -> {}
est censé représenter la logique personnalisée que quelqu'un a besoin? Donc, il serait mieux dit que() -> { /* Code here */ }
?De l'instanciation de l'interface donne un nettoyeur de séparation entre votre code et de la mise en œuvre de threads, donc je préfère le mettre en œuvre Praticable dans ce cas.
Tout le monde ici semble penser que la mise en œuvre des Exécutables est le chemin à parcourir et je n'ai pas vraiment en désaccord avec eux, mais il ya aussi un cas pour l'extension de Fil à mon avis, en fait, vous avez sorte de démonstration dans votre code.
Si vous mettez en œuvre Exécutable, puis la classe qui implémente Runnable n'a aucun contrôle sur le nom du thread, c'est le code d'appel que l'on peut définir le nom du thread, comme suit:
mais si vous étendez le Fil puis vous arrivez à gérer à l'intérieur de la classe elle-même (comme dans votre exemple vous nom le thread 'ThreadB'). Dans ce cas, vous:
) Peut donner un nom utile à des fins de débogage
B) sont en train de forcer qui que ce nom sera utilisé pour toutes les instances de cette classe (sauf si vous ignorez le fait qu'il s'agit d'un fil et faire avec elle comme si c'est un Exécutable, mais nous parlons de la convention de ici en tout cas, de manière peut ignorer la possibilité que je ressens).
Vous pourriez même, par exemple, une trace de la pile de sa création et de l'utiliser comme le nom du thread. Cela peut sembler étrange, mais selon la façon dont votre code est structuré, il peut être très utile à des fins de débogage.
Cela peut sembler une petite chose, mais lorsque vous avez une application complexe avec beaucoup de discussions et tout d'un coup les choses ont interrompu "(soit pour des raisons de blocage ou peut être à cause d'une faille de sécurité dans un protocole de réseau qui serait un peu moins évident, sans fin ou d'autres raisons), puis l'obtention d'un vidage de pile de Java où tous les fils 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 par leur trace de la pile ne soit pas toujours possible si vous utilisez des groupes de plusieurs threads exécutent tous le même code).
Avoir dit que vous pouvez bien sûr aussi faire le ci-dessus de façon générique par la création d'une extension de la classe thread qui définit son nom à une trace de la pile de sa création, d'appel et ensuite l'utiliser avec votre Exécutable implémentations au lieu de la norme java de la classe Thread (voir ci-dessous) mais en plus de la trace de la pile, il pourrait être plus spécifique au contexte de l'information qui serait utile dans le nom du thread pour le débogage (une référence à l'une des nombreuses files d'attente ou les sockets, il pourrait de traitement par exemple, dans ce cas, vous préférerez peut-être étendre Fil spécialement pour ce cas, de sorte que vous pouvez avoir le compilateur force de vous (ou d'autres) à l'aide de vos bibliothèques) pour passer certaines informations (par exemple, la file d'attente/socket en question) pour une utilisation dans le nom).
Voici un exemple de générique fil avec la pile d'appel de trace comme son nom l':
et voici un échantillon de la sortie de comparer les deux noms:
Runnable
peut en effet contrôler le nom du thread, le thread qui exécute le code est, par définition, le thread courant (et tout le code qui passe les contrôles de sécurité a le contrôle sur les filetages des noms). En considérant que vous avez consacrer la moitié de votre post "omg, ce sujet de thread noms!", cela me semble un peu grosse affaire.Praticable parce que:
Praticable la mise en œuvre d'étendre
une autre classe
l'exécution
exécutable à partir d'un Pool de Threads, le
événement de fil, ou de toute autre manière dans
l'avenir.
Même si vous n'avez pas besoin de tout cela maintenant, vous pouvez à l'avenir. Depuis il n'y a aucun avantage à la redéfinition de Fil, Runnable est une meilleure solution.
Puisque c'est un sujet très populaire et les bonnes réponses sont répartis sur tout et traitées en profondeur, j'ai senti qu'il est justifiable de compiler les bonnes réponses de la part des autres dans une forme plus concise, de sorte que les nouveaux arrivants ont une vue d'ensemble facile initial:
Vous généralement d'étendre une classe pour ajouter ou modifier les fonctionnalités. Donc, si vous ne voulez pas à remplacer tout comportement de Thread, puis utiliser l'Exécutable.
Dans la même lumière, si vous n'avez pas besoin à hériter thread méthodes, vous pouvez le faire sans que généraux en utilisant l'Exécutable.
De 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 l'Exécutable.
Il est bon de séparer le domaine de la logique de moyens techniques, en ce sens, il est préférable d'avoir un Exécutable tâche isoler votre tâche de votre coureur.
Vous pouvez exécuter le même Exécutable objet à plusieurs reprises, un objet Thread, cependant, ne peut être lancé qu'une seule fois. (Peut-être la raison, pourquoi les Exécuteurs faire accepter Runnables, mais pas de Fils.)
Si vous développez votre tâche Exécutable, vous avez toute souplesse comment l'utiliser maintenant et dans l'avenir. Vous pouvez exécuter simultanément par les Exécuteurs testamentaires, mais également par le Thread. Et vous pourriez aussi utiliser/appel de la non-simultanément dans le même thread, comme n'importe quel autre type d'objet.
Cela rend également plus facile à séparé à la tâche de la logique et de la simultanéité aspects votre tests unitaires.
Si vous êtes intéressé par cette question, vous pourriez aussi être intéressé par les différence entre Appelable et Praticable.
Différence entre l'Extension de Fil et la mise en Œuvre de Exécutables sont:
Cette question est abordée dans d'Oracle Définition et lancement d'un Thread tutoriel:
En d'autres termes, la mise en œuvre de
Runnable
va travailler dans les scénarios où votre classe étend une classe autre queThread
. Java ne supporte pas l'héritage multiple. Aussi, l'extension deThread
ne sera pas possible lors de l'utilisation de certains de haut niveau thread de gestion des Api. Le seul scénario où l'extensionThread
est préférable dans une petite application qui ne sera pas sujet à des mises à jour à l'avenir. Il est presque toujours préférable de mettre en œuvreRunnable
car il est plus souple que votre projet se développe. Un changement de conception de ne pas avoir un impact majeur que vous pouvez implémenter plusieurs interfaces en java, mais seulement d'étendre une classe.Si je ne me trompe pas, c'est plus ou moins similaire à
Quelle est la différence entre une interface et une classe abstraite?
s'étend établit "Est Un" rapport & interface fournit "A un" la capacité.
Préfèrent implements Runnable :
Préfèrent "extends Thread" :
En général, vous n'avez pas besoin de remplacer Thread comportement. Donc implements Runnable est préféré pour la plupart du temps.
Sur une note différente, en utilisant advanced
ExecutorService
ouThreadPoolExecutorService
API fournit plus de flexibilité et de contrôle.Jetez un oeil à cette Question SE:
ExecutorService vs Casual Fil des Reproducteurs
L'explication la plus simple serait par la mise en œuvre de
Runnable
on peut attribuer le même objet à plusieurs threads et chaqueThread
partage le même objet unis et le comportement.Par exemple, supposons qu'il existe deux threads, thread1 met un entier dans un tableau et thread2 prend des entiers à partir de la matrice lorsque le tableau est rempli. Notez que pour thread2 de travail, il a besoin de connaître l'état de la matrice, qu'il thread1 a rempli ou non.
La mise en œuvre de
Runnable
vous permet de disposer de la flexibilité nécessaire pour partager l'objet alors queextends Thread
vous fait pour créer de nouveaux objets pour chaque threads donc toute mise à jour qui est fait par thread1 est perdu à thread2.La séparation de la classe Thread à partir de l'Exécutable de mise en œuvre permet aussi d'éviter de potentiels problèmes de synchronisation entre le fil et la méthode run (). Séparé Praticable donne généralement une plus grande flexibilité dans la façon dont exécutable, le code est référencé et exécuté.
C'est le S de SOLIDE: Seule la responsabilité.
Un fil incarne la de course contexte (comme dans le contexte d'exécution: la trame de pile, l'id de thread, etc.) de la d'exécution 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 le bundle ensemble en une seule application, vous donnez de l'objet résultant de deux sans rapport avec causes de changement:
Si la langue que vous utilisez prend en charge partielle des classes ou de l'héritage multiple, vous pouvez séparer chaque cause dans son propre super classe, mais ça revient au même que de composer les deux objets, car 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 de transporter plus de complexité que nécessaire. Si vous avez un thread de travail sur une tâche spécifique, sans jamais changer cette tâche, il est probablement inutile de faire les tâches des classes séparées, et votre code est plus simple.
Dans le contexte de Java, depuis l'installation est déjà là, il est probablement plus facile de démarrer directement avec stand alone
Runnable
classes, et de transmettre leurs instances pourThread
(ouExecutor
) des cas. Une fois utilisé pour ce motif, il n'est pas plus difficile à utiliser (ou même de lire) que la simple exécutable thread cas.Une raison pour laquelle vous voulez mettre en œuvre une interface plutôt que d'étendre une classe de base est que vous êtes déjà l'extension d'une autre classe. Vous ne pouvez étendre une classe, mais vous pouvez mettre en œuvre un nombre quelconque d'interfaces.
Si vous étendez le Thread, vous êtes essentiellement en empêchant votre logique pour être exécuté par un autre thread que 'cette'. Si vous ne voulez certains thread pour exécuter votre logique, il est préférable de simplement mettre en œuvre Praticable.
si vous utilisez l'exécutable, vous pouvez économiser de l'espace pour s'étendre à d'aucune autre classe.
Peut-on re-visiter la raison fondamentale pour laquelle nous avons voulu que notre de classe à se comporter comme une
Thread
?Il n'y a pas de raison à tous, nous voulions juste à l'exécution d'une tâche, le plus probable dans un mode asynchrone, ce qui signifie précisément que l'exécution de la tâche doit se branche à partir de notre sujet principal et le thread principal si se termine tôt, peut ou ne peut pas attendre pour le ramifiée chemin(de la tâche).
Si c'est le but, alors, où puis-je voir la nécessité d'une institution spécialisée des Thread. Ceci peut être accompli en ramassant les RAW d'un Thread du Pool de Threads et de l'affecter notre tâche (peut être une instance de notre classe) et c'est tout.
Alors laissez-nous obéir à la Oups concept et écrire une classe du type dont nous avons besoin. Il existe de nombreuses façons de faire les choses, dans le droit chemin les questions.
Nous avons besoin d'une tâche, afin d'écrire une définition de tâche qui peut être exécuté sur un Fil. Donc, utiliser l'Exécutable.
Rappelez-vous toujours
implements
est spécialement utilisé pour transmettre un comportement etextends
est utilisé pour conférer une caractéristique ou de la propriété.Nous ne voulons pas que le thread de la propriété, au lieu de cela, nous voulons que notre de classe à se comporter comme une tâche qui peut être exécuté.
Oui,
Si vous appelez ThreadA appel , alors pas besoin d'appeler la méthode start et de la méthode run est l'appel après appel de la ThreadA classe seulement.
Mais Si l'utilisation du ThreadB appel doivent ensuite nécessaire le début de thread pour appeler la méthode run.
Si vous avez plus de l'aide, de me répondre.
Je trouve qu'il est plus utile d'utiliser Praticable pour toutes les raisons mentionnées, mais parfois, j'aime à prolonger Thread donc je peux créer mon propre thread méthode d'arrêt et de l'appeler directement sur le fil que j'ai créé.
Java ne supporte pas l'héritage multiple, donc si vous étend la classe Thread alors aucune autre classe sera étendu.
Par Exemple: Si vous créez une applet, puis il doit s'étend classe Applet donc, ici, la seule façon de créer de thread est en implémentant l'interface Runnable
Runnable
est une interface, alors queThread
est une classe qui implémente cette interface. À partir d'une conception de point de vue, il devrait y avoir une séparation nette entre la manière dont une tâche est définie et entre la manière dont il est exécuté. Le premier est la responsabilité d'unRunnalbe
mise en œuvre, et la dernière est emploi de laThread
classe. Dans la plupart des cas, la mise en œuvre deRunnable
est la bonne route à suivre.Différence entre le Fil et praticable
.Si nous sommes la création de Thread à l'aide de Fil de classe Nombre de thread égal au nombre d'objet que nous avons créé .
Si nous sommes la création de thread par l'implémentation de l'interface runnable alors nous pouvons utiliser un seul objet à la création de plusieurs threads.Si un seul objet est partagé par plusieurs Threads.Donc il va prendre moins de mémoire
Alors, selon le besoin, si nos données ne sont pas sensibles. De sorte qu'Il peut être partagé entre plusieurs Threads nous pouvons nous servir de l'interface Runnable.
Ajouter mon grain de sel ici -
Toujours chaque fois que possible, utiliser
implements Runnable
. Ci-dessous, deux mises en garde sur pourquoi vous ne devriez pas utiliserextends Thread
sIdéalement, vous ne devriez jamais étendre la classe Thread; la
Thread
catégorie devraient êtrefinal
.Au moins ses méthodes comme
thread.getId()
.Voir cette discussion d'un bug lié à l'extension de
Thread
s.Ceux qui aiment résoudre des énigmes pouvez en voir un autre effet secondaire de l'extension de Fil. Le code ci-dessous
imprime code inaccessible lorsque personne n'est à l'informant.
Veuillez voir http://pastebin.com/BjKNNs2G.
Une différence entre la mise en œuvre Praticable et l'extension de discussion est que par l'extension de Fil, chacun de votre fils a un unique objet associé, tandis que la mise en œuvre des Exécutables, de nombreux threads peuvent partager la même instance d'objet.
Une classe qui implémente Runnable n'est pas d'un fil, juste une classe. Pour un Exécutable à être exécuté par un Thread, vous devez créer une instance de Thread et de passer l'Exécutable de l'instance en tant que cible.
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. Mais si nous venons d'étendre la classe Thread on ne peut pas hériter d'une autre classe.
La meilleure façon pour la plupart des threads de travail est d'avoir le filetage complètement encapsulé dans la catégorie des travailleurs de sorte que rien ne peut interférer de l'extérieur et de causer des invalides thread/classe unis.
J'ai juste posté un exemple, donc je vais aussi partager avec vous:
Thread est titulaire d'un comportement qui n'est pas destiné à être consulté;
toutefois, si vous sous-classe de Thread envisager plus de Fil est mis en œuvre.
Si vous exécutez ce que vous pourrait s'attendre à ce
cependant, vous n'êtes pas en appelant la méthode que vous pensez que vous êtes parce que vous êtes à l'aide de la méthode dans
Thread
pasThreadMain
et au lieu de cela, vous voyez quelque chose commeCe n'est peut-être pas une réponse, mais de toute façon; il n'y a plus d'une façon de créer des threads:
Dans les rares cas où vous ne l'exécuter une fois, vous devez étendre Fil en raison de la SEC. Si vous appelez plusieurs fois, vous devez mettre en œuvre Praticable parce que le même fil ne doit pas être redémarré.
Par l'extension de la classe thread , la classe dérivée ne peut pas s'étendre à tous les autres de la classe de base parce que java permettent seulement de l'héritage simple.
au contraire, Par la mise en œuvre de l'exécutable de l'interface de la classe toujours étendre à d'autres de la classe de base.
Par l'extension de Fil, dérivée de la classe elle-même est un objet thread, alors que l'Implémentation de l'interface Runnable il partage le même objet de plusieurs Threads.
1. L'extension de la thread de l'interface, est que vous faites de votre classe à se comporter comme un fil. Votre nouvelle classe sera comme une meilleure thread.
Il crée un thread, pas la
Test
objet. Il va agir comme un seul thread. Vous ne pouvez pas partager l'instance deTest
de classe entre les threads.2. L'implémentation de l'interface runnable.
Cet objet peuvent être partagées entre les threads par,
Je pense qu'il y a déjà beaucoup qui a été discuté sur ce sujet, pensé que cela pourrait être utile autour de la base.
Façon Simple de dire, c'est:
Si vous implémentez l'interface qui signifie que vous êtes la mise en œuvre de toutes les méthodes de lui et si vous l'extension de la classe héritant de la méthode de votre choix...
Dans ce cas,il est une seule méthode Run() donc préférable d'implémenter l'interface Runnable..
Classe Thread définit plusieurs méthodes qui peuvent être
overriden
par l'extension de la classe. Mais pour créer un thread, nous devons remplacer larun()
méthode. Même s'applique àRunnable
ainsi.Cependant
Runnable
est une méthode préférée de création d'un thread. Les principales raisons sont:Depuis Exécutable est une interface, vous pouvez l'étendre à d'autres classes. Mais si vous étendez Thread alors que l'option a disparu.
Si vous n'êtes pas la modification ou l'amélioration de tout un tas de
Thread
fonctionnalités et l'extension de laThread
classe n'est pas un moyen privilégié.Je dirais tâche réelle est découplé du fil. Nous pouvons passer autour de la tâche à Fil, de l'Exécuteur testamentaire cadre etc dans le cas de l'Exécutable, alors qu'avec l'extension de Fil tâche est couplé avec du fil objet lui-même. La tâche de l'isolement ne peut être fait dans le cas de l'extension de Fil. C'est comme si nous brûler la tâche pour objet Thread juste quelque chose comme de la puce (et plus particulièrement de ne pas obtenir une poignée à la tâche).
La principale différence entre le Fil et l'Exécutable est:
- Fil est comme: Travailleur (exécuter Exécutables)
- Exécutable est comme: Travail (pour être exécuté par le Thread)
Vous pouvez les utiliser conjointement
Exemple :
new Thread(new A())
et invoquerstart()
méthode au lieu derun()
.