Wann würden Sie Java's thread.run () anstelle von thread.start () aufrufen?

109

Wann würden Sie Java thread.run()anstelle von anrufen thread.start()?

leer
quelle
47
Wann bin ich die thread.start () Methode? :)
Bill the Lizard
3
@blank, Die Antwort lautet einfach: t.run()Wenn Sie die tAufgabe im aktuellen Thread t.start()ausführen möchten und wenn Sie die tAufgabe im Thread tselbst ausführen möchten . Oder fragen Sie nach tatsächlichen Anwendungsfällen?
Pacerier
2
Wenn Sie ein Idiot sind und eine Stunde damit verbringen möchten, Multithread-Code zu debuggen, um später zu erkennen, dass Sie einfach hätten anrufen sollen start()! Wie ich ... Diese Methode sollte nicht öffentlich sein!
Pierre Henry

Antworten:

113

Möglicherweise möchten Sie run () in einem bestimmten Komponententest aufrufen, der sich ausschließlich mit der Funktionalität und nicht mit der Parallelität befasst.

Paul Croarkin
quelle
95

Noch nie. Das direkte Aufrufen von run () führt den Code direkt synchron aus (im selben Thread), genau wie ein normaler Methodenaufruf.

Adam Crume
quelle
25
"Niemals" ist etwas zu absolut. Vielleicht möchten Sie nicht immer einen neuen Thread und führen den Code trotzdem aus?
Tomalak
4
Vielleicht, aber in diesem Fall wäre es unnötig verschwenderisch, einen neuen Thread zu erstellen, nur um die run () -Methode aufzurufen. Es ist besser, ein Runnable-Impl zu erstellen und entweder diesen In-Thread auszuführen oder einen neuen Thread damit zu erstellen.
Scott Bale
1
Nur noch einmal besuchen ... wenn nie, warum ist die Methode öffentlich?
leer
4
Es ist öffentlich, weil Thread Runnable implementiert. Sie können Thread in Unterklassen unterteilen und run () überschreiben. Dies hat den gleichen Effekt, als würden Sie Ihren Code in eine ausführbare Datei einfügen und diesen an den Thread-Konstruktor übergeben. Es ist jedoch besser, ein separates ausführbares Objekt zu verwenden, da Sie dadurch mehr Flexibilität haben (z. B. die Übergabe an einen Executor usw.).
Adam Crume
2
Lassen Sie mich ein konkretes Beispiel geben, mit dem ich gerade arbeite: Ich habe ein Programm, das entweder als GUI oder über die Befehlszeile ausgeführt werden kann. Im GUI-Fall möchte ich, dass das Objekt, das das schwere Heben ausführt, auf einem separaten Thread ausgeführt wird und Aktualisierungen an die GUI sendet. Im Befehlszeilenmodus benötige ich diesen separaten Thread nicht.
Edward Falk
27

Entnommen aus den FAQ zu Java-Threads im Codestil :

F: Was ist der Unterschied zwischen den Methoden start () und run () eines Threads?

A: Die getrennten Methoden start () und run () in der Thread-Klasse bieten zwei Möglichkeiten zum Erstellen von Thread-Programmen. Die Methode start () startet die Ausführung des neuen Threads und ruft die Methode run () auf. Die start () -Methode wird sofort zurückgegeben und der neue Thread wird normalerweise fortgesetzt, bis die run () -Methode zurückgegeben wird.

Die run () -Methode der Thread-Klasse führt nichts aus, daher sollten Unterklassen die Methode mit Code überschreiben, der im zweiten Thread ausgeführt werden soll. Wenn ein Thread mit einem Runnable-Argument instanziiert wird, führt die run () -Methode des Threads stattdessen die run () -Methode des Runnable-Objekts im neuen Thread aus.

Abhängig von der Art Ihres Thread-Programms kann der direkte Aufruf der Thread run () -Methode dieselbe Ausgabe liefern wie der Aufruf über die start () -Methode. Im letzteren Fall wird der Code jedoch tatsächlich in einem neuen Thread ausgeführt.

Tomalak
quelle
thread's run() method executes the run() method of the Runnable object in the new thread instead.Das ist nicht wahr (oder zumindest mein Java 8-Quellcode sagt etwas anderes aus), aber leider scheint der Link unterbrochen zu sein, so dass ich den Fehler stattdessen hier melde.
Kajacx
1
@Tomalak, Dies beantwortet die gestellte Frage nicht. Die Frage fragt nicht nach dem Unterschied, sondern nach Anwendungsfällen, bei denen wir thread.run()stattdessen anrufen thread.start().
Pacerier
24

Durch das Ausführen thread.run()wird kein neues ThreadCode erstellt, in dem Ihr Code ausgeführt wird. Es wird nur der Code im aktuellen Thread ausgeführt, von dem aus der thread.run()Code aufgerufen wird.

Durch Ausführen thread.start()wird ein neuer Thread auf Betriebssystemebene erstellt, in dem die run()Methode aufgerufen wird.

Im Wesentlichen:

Single Threaded Programmierung → Direktes Aufrufen der run()Methode

Multithread-Programmierung → start()Methode aufrufen

Darüber hinaus scheint "Testen", wie andere bereits erwähnt haben, der einzig ratsame Fall zu sein, in dem Sie run()direkt von Ihrem Code aus aufrufen können.

Mahendra Liya
quelle
13

Dies wurde bereits angedeutet, aber um es klar zu machen: Das Erstellen eines neuen Thread-Objekts nur zum Aufrufen seiner run () -Methode ist unnötig teuer und sollte eine wichtige rote Fahne sein. Es wäre ein viel besseres, entkoppelteres Design, ein Runnable-Impl zu erstellen und entweder (a) die run () -Methode direkt aufzurufen , wenn dies das gewünschte Verhalten ist, oder (b) einen neuen Thread mit diesem Runnable zu erstellen und den Thread zu starten.

Besser noch, für noch mehr Entkopplung sehen Sie sich die ExecutorSchnittstelle und das Framework in JDK 5 und höher an . Dies ermöglicht es Ihnen, in aller Kürze, zu entkoppeln Aufgabenausführung (die Runnable Instanz) aus , wie er ausgeführt wird (die Executor - Implementierung, die die Runnable in dem aktuellen Thread ausführen könnte, in einem neuen Thread, ein vorhandenes Thema aus einem Pool verwenden, und was nicht).

Scott Bale
quelle
9

Rufen Sie an thread.start(), es wird wiederum anrufen thread.run(). Ich kann mir keinen Fall vorstellen, in dem Sie umgehen thread.start()und direkt zu gehen möchtenthread.run()

Chris Ballance
quelle
3
Während des Testens ist der einzige legitime Fall, an den ich denken kann. Andernfalls sollte sich der Inhalt von run () in einer separaten Methode befinden, die von run oder auf andere Weise aufgerufen wird.
Bill the Lizard
9

Die separaten start()und run()Methoden in der Thread-Klasse bieten zwei Möglichkeiten zum Erstellen von Thread-Programmen. Die start()Methode startet die Ausführung des neuen Threads und ruft die run()Methode auf. Die start()Methode wird sofort zurückgegeben und der neue Thread wird normalerweise fortgesetzt, bis die run()Methode zurückgegeben wird.

Die run()Methode der Thread-Klasse führt nichts aus, daher sollten Unterklassen die Methode mit Code überschreiben, der im zweiten Thread ausgeführt werden soll. Wenn ein Thread mit einem Runnable-Argument instanziiert wird, führt die Thread- run()Methode run()stattdessen die Methode des Runnable-Objekts im neuen Thread aus.

Abhängig von der Art Ihres Thread-Programms kann das run()direkte Aufrufen der Thread- Methode dieselbe Ausgabe liefern wie das Aufrufen über die start()Methode. Im letzteren Fall wird der Code jedoch tatsächlich in einem neuen Thread ausgeführt.

Referenz

alok
quelle
Gleich wie Tomalak Antwort !! Wenn Sie von irgendwoher verwiesen haben, erwähnen Sie das bitte !!
Barry
The start() method returns immediately and the new thread normally continues until the run() method returns.Wenn start()sofort zurückkommt, wie kommt es, dass der run()weiterhin läuft, da er selbst vonstart()
KNU
7

Wenn die Frage lautete: "Warum wird die Thread-Startmethode aufgerufen, anstatt die Methode direkt auszuführen?", Habe ich unten mit einem Beispielcode geantwortet. Hoffe das klärt. Im folgenden Beispiel:

/*
By calling t1.start(), 
we are getting the main calling thread returned immediately 
after the t1.start() called and is ready to proceed for other 
operations.And the thread t1 starts executing the run method of the object r. 
Hence the the output will be:

      I am the main thread , i created thread t1 and had it execute run method, which is currently looping from 0 to 1000000

      I am done executing run method of testThread

*/


/* If we call t1.run() instead of t1.start(), (just replace t1.start() with t1.run() in the code for testing)
 its like a regular method call and the main thread will not return until the run method completes, 
 hence the output will be:

         I am done executing run method of testThread

         I am the main thread , i created thread t1 and had it execute run method, which is currently looping for i to 1000000

*/


class testThread implements Runnable{

 public void run()
 {
     for(int i=0;i<1000000;i++){} //a simple delay block to clarify.

     System.out.println("I am done executing run method of testThread");

 }  
}

public class mainClass{

   public static void main(String [] args)
    {
          testThread r = new testThread();
          Thread t1 = new Thread(r);
          t1.start();  /* Question is: can we call instead t1.run() */  
          System.out.println("I am the main thread , i created thread t1 and had it execute run method, which is currently looping for i to 1000000");

    }
}
Steer360
quelle
5

Wenn Sie möchten, dass es synchron ausgeführt wird. Wenn Sie die run-Methode aufrufen, erhalten Sie kein Multithreading. Die Startmethode erstellt einen neuen Thread, der die Ausführungsmethode aufruft.

Brian
quelle
3

Wenn Sie den Inhalt von run () wie bei jeder anderen Methode ausführen möchten. Natürlich, um keinen Thread zu starten.


quelle
3

Angenommen, Sie kennen die Verwendung der Start- und Ausführungsmethode, dh synchron oder asynchron. Die run-Methode kann nur zum Testen der Funktionalität verwendet werden.

Unter bestimmten Umständen kann dieselbe Thread-Klasse an zwei verschiedenen Stellen mit Anforderungen an die Synchronisierungs- und Asynch-Funktionalität verwendet werden, indem zwei verschiedene Objekte mit der Aufführungsmethode der einen und der Startmethode der anderen aufgerufen werden.

Salman Kasbati
quelle
2

Zumindest in der JVM 1.6. Wird ein bisschen überprüft und ausgeführt wird nativ aufgerufen:

 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();
Steve B.
quelle
2

Nur eine Anmerkung zu den obigen tollen Kommentaren: Manchmal schreiben Sie einen Multithread-Code, der die "Start" -Methode verwendet, um verschiedene Threads auszuführen. Sie werden es viel einfacher finden, wenn Sie "run" (anstelle von "start)" zum Debuggen verwenden, da dadurch der Code synchron ausgeführt und das Debuggen viel einfacher wird.

msamadi
quelle
-1
public class TestClass implements Runnable {
    public static void main(String[] args) {
        TestClass tc = new TestClass();

        Thread t1 = new Thread(tc);
        System.out.println("Before Starting Thread " + Thread.currentThread().hashCode());
        t1.start();
        System.out.println("After Starting Thread " + Thread.currentThread().hashCode());
    }

    @Override
    public void run() {
        System.out.println("TestClass Run method is  Running with thread " + Thread.currentThread().hashCode());        
    }
}
Avatar Girase
quelle
Hallo Frnz, check out und führe das obige Beispiel aus, um zu verstehen, dass du zuerst mit t1.start () und dem Hashcode und beim nächsten Mal mit t1.run () und chk Hashcodes
Avatar Girase
Wo ist deine Frage?
Amen Jlili