Quelle est la différence entre Thread start () et Runnable run ()


224

Disons que nous avons ces deux Runnables:

class R1 implements Runnable {
    public void run() {  }
    
}

class R2 implements Runnable {
    public void run() {  }
    
}

Alors quelle est la différence entre ceci:

public static void main() {
    R1 r1 = new R1();
    R2 r2 = new R2();

    r1.run();
    r2.run();
}

Et ça:

public static void main() {
    R1 r1 = new R1();
    R2 r2 = new R2();
    Thread t1 = new Thread(r1);
    Thread t2 = new Thread(r2);

    t1.start();
    t2.start();
}

Réponses:


309

Premier exemple: pas de plusieurs threads. Les deux s'exécutent dans un seul thread (existant). Aucune création de thread.

R1 r1 = new R1();
R2 r2 = new R2();

r1et ne r2sont que deux objets de classes différents qui implémentent l' Runnableinterface et donc implémentent la run()méthode. Lorsque vous appelez, r1.run()vous l'exécutez dans le thread actuel.

Deuxième exemple: deux threads séparés.

Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);

t1et t2sont des objets de la classe Thread. Lorsque vous appelez t1.start(), il démarre un nouveau thread et appelle la run()méthode de l' r1interne pour l'exécuter dans ce nouveau thread.


5
Couuld je considère qu'avant d'appeler Thread # start (), rien de vraiment relatif au thread os ne se produit? Ce n'est qu'un objet java.
Jaskey

4
C'est correct selon la documentation. Vérifiez le code d'initialisation de l'objet thread, conforme à la documentation. Également dans le code source, c'est le start(), qui appelle une méthode natvie, qui doit faire en sorte que les choses liées au thread os se produisent.
Bhesh Gurung

3
La documentation du constructeur de threads est ici . La source d'initialisation de l'objet thread est ici . start()la source de la méthode est ici .
Bhesh Gurung

92

Si vous venez d'appeler run()directement, il est exécuté sur le thread appelant, comme tout autre appel de méthode. Thread.start()est nécessaire pour créer un nouveau thread afin que la runméthode de runnable soit exécutée en parallèle.


2
Dans Hotspot JVM, il existe une correspondance directe entre le thread java et le thread natif. Thread.start()l'invocation fait passer l'état du thread du nouvel état à l' état Runnable . Runnable ne signifie pas que le thread est en cours d'exécution. Une fois le thread natif initialisé, le thread natif invoque la run()méthode dans le thread Java, ce qui fait passer l'état du thread de Runnable à Running . Lorsque le thread se termine, toutes les ressources pour le thread natif et Java sont libérées.
suréchange

@overexchange Où puis-je trouver des informations sur le changement d'état.
twlkyao

73

La différence est que Thread.start()démarre un thread qui appelle la run()méthode, alors Runnable.run()qu'il appelle simplement la run()méthode sur le thread actuel.


35

La différence est que lorsque le programme appelle la start()méthode, un nouveau thread est créé et le code à l'intérieur run()est exécuté dans le nouveau thread tandis que si vous appelez run()directement la méthode, aucun nouveau thread ne sera créé et le code à l'intérieur run()s'exécutera directement dans le thread actuel.

Une autre différence entre start()et run()dans le thread Java est que vous ne pouvez pas appeler start()deux fois. Une fois lancé, le deuxième start()appel lancera IllegalStateExceptionJava tandis que vous pouvez appeler run()plusieurs fois la méthode car il s'agit simplement d'une méthode ordinaire .


21

Crée en fait Thread.start()un nouveau thread et possède son propre scénario d'exécution.

Thread.start()appelle la run()méthode de manière asynchrone, ce qui change l'état du nouveau thread en Runnable.

Mais Thread.run()ne crée pas de nouveau thread. Au lieu de cela, il exécute la méthode d'exécution dans le thread en cours d'exécution de manière synchrone.

Si vous utilisez, Thread.run()vous n'utilisez pas du tout les fonctionnalités du multi-threading.


8

invoke run()s'exécute sur le thread appelant, comme tout autre appel de méthode. alors Thread.start()crée un nouveau fil. invoquer run()est un bug programmatique.


7

Si vous le faites run()dans la méthode principale, le thread de la méthode principale invoquera la runméthode au lieu du thread que vous souhaitez exécuter.

La start()méthode crée un nouveau thread et pour lequel la run()méthode doit être effectuée


La «méthode principale» n'a rien à voir avec cela.
Marquis de Lorne

3
@EJP, par mainl'auteur, signifiait la méthode d'appel. Sa réponse est assez bonne. +1 ;-)
dom_beau

1
@dom_beau Si c'est ce qu'il voulait dire, il aurait dû le dire. Ce qu'il a dit était incorrect. Il n'y a rien de «assez bon» dans cette réponse. C'est juste un désordre confus.
Marquis de Lorne

5

t.start() est la méthode que la bibliothèque fournit pour que votre code appelle lorsque vous voulez un nouveau thread.

r.run()est la méthode que vous fournissez pour que la bibliothèque appelle dans le nouveau thread.


La plupart de ces réponses manquent de vue d'ensemble, c'est-à-dire qu'en ce qui concerne le langage Java, il n'y a pas plus de différence entre t.start()et r.run()qu'il n'y a entre deux autres méthodes.

Ce ne sont que des méthodes. Ils courent tous les deux dans le fil qui les a appelés . Ils font tous les deux ce pour quoi ils ont été codés, puis ils retournent tous les deux, toujours dans le même fil, à leurs appelants.

La plus grande différence est que la majeure partie du code de t.start()est du code natif tandis que, dans la plupart des cas, le code r.run()de sera pur Java. Mais ce n'est pas vraiment une différence. Le code est le code. Le code natif est plus difficile à trouver et plus difficile à comprendre lorsque vous le trouvez, mais c'est toujours du code qui indique à l'ordinateur quoi faire.

Alors, qu'est-ce que ça t.start()fait?

Il crée un nouveau thread natif, il organise l'appel de ce thread t.run(), puis il indique au système d'exploitation de laisser le nouveau thread s'exécuter. Puis il revient.

Et que fait r.run()-il?

Le plus drôle, c'est que la personne qui pose cette question est celle qui l'a écrite . r.run()fait tout ce que vous (c'est-à-dire le développeur qui l'a écrit) avez conçu.


4

Thread.start()code enregistre le thread avec le planificateur et le planificateur appelle la run()méthode. En outre, Threadest la classe while Runnableest une interface.


3

Les points soulevés par les membres sont très bien, donc je veux juste ajouter quelque chose. Le fait est que JAVA ne prend pas en charge l'héritage multiple. Mais que se passe-t-il si vous voulez dériver une classe B d'une autre classe A, mais vous ne pouvez dériver que d'une classe. Le problème est maintenant de savoir comment "dériver" des deux classes: A et Thread. Par conséquent, vous pouvez utiliser l'interface exécutable.

public class ThreadTest{
   public void method(){
      Thread myThread = new Thread(new B());
      myThread.start;
   }
}

public class B extends A implements Runnable{...

joliment explication de la méthode run () à l'aide d'un exemple sur Runnable - une interface et Thread - une classe
Pinky Walve

1

Si vous appelez directement la run()méthode, vous n'utilisez pas la fonctionnalité multithread car la run()méthode est exécutée dans le cadre du thread appelant.

Si vous appelez la start()méthode sur Thread, la machine virtuelle Java appellera la méthode run () et deux threads s'exécuteront simultanément - Thread actuel ( main()dans votre exemple) et Autre thread (Runnable r1dans votre exemple).

Jetez un œil au code source de la start()méthode dans la classe Thread

 /**
     * Causes this thread to begin execution; the Java Virtual Machine
     * calls the <code>run</code> method of this thread.
     * <p>
     * The result is that two threads are running concurrently: the
     * current thread (which returns from the call to the
     * <code>start</code> method) and the other thread (which executes its
     * <code>run</code> method).
     * <p>
     * It is never legal to start a thread more than once.
     * In particular, a thread may not be restarted once it has completed
     * execution.
     *
     * @exception  IllegalThreadStateException  if the thread was already
     *               started.
     * @see        #run()
     * @see        #stop()
     */
    public synchronized void start() {
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();
        group.add(this);
        start0();
        if (stopBeforeStart) {
            stop0(throwableFromStop);
        }
    }

    private native void start0();

Dans le code ci-dessus, vous ne pouvez pas voir l'invocation à la run()méthode.

private native void start0()est responsable de la run()méthode d' appel . JVM exécute cette méthode native.


0

Dans le premier cas, vous invoquez simplement la run()méthode des objets r1et r2.

Dans le deuxième cas, vous créez en fait 2 nouveaux threads!

start()appellera run()à un moment donné!


7
En fait, start () n'appellera pas run (): si c'était le cas, alors la méthode run () serait exécutée par le même thread qui appelait start (). Ce que start () fera est de créer un thread qui appellera la méthode run ().
Bruno Reis

0

méthode d'exécution: - est une méthode abstraite créée à l'origine dans l'interface Runnable et remplacée dans la classe Thread ainsi que dans les sous-classes Thread (As Thread implémente Runnable dans son code source) et toutes les autres classes d'implémentation de l'interface Runnable. - Il est utilisé pour charger le thread (objet exécutable) avec la tâche qu'il est destiné à effectuer, vous le remplacez donc pour écrire cette tâche.

méthode de démarrage: - est définie dans la classe Thread. Lorsque la méthode start est appelée sur un objet Thread 1- elle appelle une méthode native (non java) interne appelée start0 (); méthode.

start0 (); méthode: est responsable du faible traitement (création de pile pour un thread et allocation du thread dans la file d'attente du processeur) à ce stade, nous avons un thread à l'état Prêt / Exécutable.

2- À un moment où le planificateur de threads décide qu'un thread entre dans un noyau de processeur pour (la priorité des threads ainsi que l'algorithme de planification du système d'exploitation) la méthode d'exécution est invoquée sur l'objet Runnable (que ce soit l'objet de thread Runnable actuel ou l'objet Runnable passé au constructeur de thread) ici, un thread entre dans un état Running et commence à exécuter sa tâche (méthode run)


-2

Les méthodes distinctes start () et run () de la classe Thread offrent deux façons de créer des programmes filetés. La méthode start () démarre l'exécution du nouveau thread et appelle la méthode run (). La méthode start () retourne immédiatement et le nouveau thread continue normalement jusqu'à ce que la méthode run () revienne.

La méthode run () de la classe Thread ne fait rien, les sous-classes doivent donc remplacer la méthode par du code à exécuter dans le deuxième thread. Si un thread est instancié avec un argument Runnable, la méthode run () du thread exécute à la place la méthode run () de l'objet Runnable dans le nouveau thread.

Selon la nature de votre programme threadé, l'appel direct de la méthode Thread run () peut donner la même sortie que l'appel via la méthode start (), mais dans ce dernier cas, le code est en fait exécuté dans un nouveau thread.


2
Appeler `run () 'n'est pas un moyen de créer des programmes threadés. Il n'y a qu'une seule façon.
Marquis de Lorne

-2

La méthode Start () appelle la méthode run override de la classe étendue Thread et l'interface des outils Runnable.

Mais en appelant run (), il recherche la méthode d'exécution mais si la classe implémente l'interface Runnable, alors il appelle la méthode de remplacement run () de Runnable.

ex.:

"

public class Main1
{
A a=new A();
B b=new B();
a.run();//This call run() of Thread because run() of Thread only call when class 
        //implements with Runnable not when class extends Thread.
b.run();//This not run anything because no run method found in class B but it 
        //didn't show any error.

a.start();//this call run() of Thread
b.start();//this call run() of Thread
}

class A implements Runnable{
@Override
    public void run() {
            System.out.println("A ");
    }
}

class B extends Thread {

    @Override
    public void run() {
            System.out.println("B ");
    }
}

"

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.