Was ist der Unterschied zwischen Thread start () und Runnable run ()


224

Angenommen, wir haben diese beiden Runnables:

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

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

Was ist dann der Unterschied zwischen diesen:

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

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

Und das:

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

Antworten:


309

Erstes Beispiel: Keine mehreren Threads. Beide werden in einem (vorhandenen) Thread ausgeführt. Keine Thread-Erstellung.

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

r1und r2sind nur zwei verschiedene Objekte von Klassen, die die RunnableSchnittstelle und damit die run()Methode implementieren . Wenn Sie aufrufen, führen r1.run()Sie es im aktuellen Thread aus.

Zweites Beispiel: Zwei separate Threads.

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

t1und t2sind Objekte der Klasse Thread. Wenn Sie aufrufen t1.start(), wird ein neuer Thread gestartet und die run()Methode r1intern aufgerufen , um ihn in diesem neuen Thread auszuführen.


5
Könnte ich bedenken, dass vor dem Aufruf von Thread # start () nichts wirklich Relatives in Bezug auf den OS-Thread passiert? Es ist nur ein Java-Objekt.
Jaskey

4
Das ist laut Dokumentation richtig. Überprüfen Sie den Initialisierungscode für Threadobjekte, der der Dokumentation entspricht. Auch im Quellcode ist es die start(), die eine Natvie-Methode aufruft, die dafür sorgen muss, dass die OS-Thread-bezogenen Dinge passieren.
Bhesh Gurung

3
Thread-Konstruktor-Dokumente finden Sie hier . Die Quelle für die Initialisierung von Thread-Objekten befindet sich hier . start()Methodenquelle ist hier .
Bhesh Gurung

92

Wenn Sie nur run()direkt aufrufen , wird es wie jeder andere Methodenaufruf im aufrufenden Thread ausgeführt. Thread.start()ist erforderlich, um tatsächlich einen neuen Thread zu erstellen, damit die runMethode der ausführbaren Datei parallel ausgeführt wird.


2
In Hotspot JVM gibt es eine direkte Zuordnung zwischen Java-Thread und nativem Thread. Thread.start()Durch Aufrufen wird der Thread-Status vom neuen Status in den ausführbaren Status verschoben . Runnable bedeutet nicht, dass der Thread ausgeführt wird. Sobald der native Thread initialisiert wurde, ruft der native Thread die run()Methode im Java-Thread auf, wodurch der Thread-Status von Runnable in Running geändert wird . Wenn der Thread beendet wird, werden alle Ressourcen für den nativen und den Java-Thread freigegeben.
Überaustausch

@overexchange Wo finde ich das Material zur Statusänderung?
Twlkyao

73

Der Unterschied besteht darin, dass Thread.start()ein Thread gestartet wird, der die run()Methode aufruft , während Runnable.run()die run()Methode nur für den aktuellen Thread aufgerufen wird.


35

Der Unterschied ist , dass bei Programmaufrufe start()Verfahren wird ein neuer Thread erstellt wird und Code innerhalb run()in ausgeführt neuen Thread während , wenn Sie anrufen run()Methode direkt kein neuer Thread erstellt werden und Code innerhalb run()direkt in den aktuellen Thread ausführen.

Ein weiterer Unterschied zwischen start()und run()im Java-Thread besteht darin, dass Sie nichtstart() zweimal aufrufen können . Nach dem Start wird beim zweiten start()Aufruf IllegalStateExceptionJava ausgelöst, während Sie die run()Methode mehrmals aufrufen können, da es sich nur um eine gewöhnliche Methode handelt.


21

Erstellt tatsächlich Thread.start()einen neuen Thread und hat ein eigenes Ausführungsszenario.

Thread.start()run()Ruft die Methode asynchron auf, wodurch der Status des neuen Threads in "Ausführbar" geändert wird.

Erstellt Thread.run()aber keinen neuen Thread. Stattdessen wird die Ausführungsmethode im aktuell ausgeführten Thread synchron ausgeführt.

Wenn Sie verwenden, verwenden Thread.run()Sie die Funktionen von Multithreading überhaupt nicht.


8

invoke run()wird wie jeder andere Methodenaufruf im aufrufenden Thread ausgeführt. wohingegen Thread.start()erstellt einen neuen Thread. Das Aufrufen run()ist ein programmatischer Fehler.


7

Wenn Sie dies run()in der Hauptmethode tun , ruft der Thread der Hauptmethode die runMethode anstelle des Threads auf, den Sie ausführen müssen.

Die start()Methode erstellt einen neuen Thread, für den die run()Methode ausgeführt werden muss


Die 'Hauptmethode' hat nichts damit zu tun.
Marquis von Lorne

3
@EJP, vom mainVerfasser gemeint die aufrufende Methode. Seine Antwort ist ziemlich gut. +1 ;-)
dom_beau

1
@dom_beau Wenn er das gemeint hat, hätte er es sagen sollen. Was er sagte, war falsch. An dieser Antwort ist nichts "ganz Gutes". Es ist nur ein verwirrtes Durcheinander.
Marquis von Lorne

5

t.start() ist die Methode, die die Bibliothek bereitstellt, damit Ihr Code aufgerufen werden kann, wenn Sie einen neuen Thread möchten.

r.run()ist das Verfahren , dass Sie für die bieten Bibliothek ruft in dem neuen Thread.


Die meisten dieser Antworten verfehlen das Gesamtbild, dh, was die Java-Sprache betrifft, gibt es keinen größeren Unterschied zwischen t.start()und r.run()als zwischen zwei anderen Methoden.

Sie sind beide nur Methoden. Sie laufen beide in dem Thread, der sie aufgerufen hat . Beide tun, wofür sie codiert wurden, und kehren dann beide, immer noch im selben Thread, zu ihren Anrufern zurück.

Der größte Unterschied ist , dass die meisten den Code für t.start()ist nativen Code , während in den meisten Fällen, für den Code r.run()reinen Java sein wird. Aber das ist kein großer Unterschied. Code ist Code. Nativer Code ist schwerer zu finden und schwerer zu verstehen, wenn Sie ihn finden, aber es ist immer noch nur Code, der dem Computer sagt, was zu tun ist.

Also, was macht t.start()das?

Es erstellt einen neuen nativen Thread, veranlasst den Aufruf dieses Threads t.run()und weist das Betriebssystem an, den neuen Thread ausführen zu lassen. Dann kehrt es zurück.

Und was macht r.run()das?

Das Lustige ist, dass die Person, die diese Frage stellt, die Person ist, die sie geschrieben hat . r.run()macht alles , wofür Sie (dh der Entwickler, der es geschrieben hat) es entworfen haben.


4

Thread.start()Code registriert den Thread beim Scheduler und der Scheduler ruft die run()Methode auf. Auch Threadist Klasse, während Runnableeine Schnittstelle ist.


3

Die Punkte, die die Mitglieder gemacht haben, sind in Ordnung, also möchte ich nur etwas hinzufügen. Die Sache ist, dass JAVA keine Mehrfachvererbung unterstützt. Was ist, wenn Sie eine Klasse B von einer anderen Klasse A ableiten möchten, aber nur von einer Klasse ableiten können? Das Problem ist nun, wie man aus beiden Klassen "ableitet": A und Thread. Daher können Sie die ausführbare Schnittstelle verwenden.

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

public class B extends A implements Runnable{...

schöne Erklärung der run () -Methode anhand eines Beispiels über Runnable - eine Schnittstelle und Thread - eine Klasse
Pinky Walve

1

Wenn Sie die run()Methode direkt aufrufen , verwenden Sie keine Multithreading-Funktion, da die run()Methode als Teil des Aufruferthreads ausgeführt wird.

Wenn Sie die start()Methode für Thread aufrufen , ruft die Java Virtual Machine die Methode run () auf und zwei Threads werden gleichzeitig ausgeführt - Current Thread ( main()in Ihrem Beispiel) und Other Thread ( r1in Ihrem Beispiel ausführbar ).

Schauen Sie sich den Quellcode der start()Methode in der Thread-Klasse an

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

Im obigen Code können Sie den Aufruf der run()Methode nicht sehen .

private native void start0()ist für den Aufruf der run()Methode verantwortlich. JVM führt diese native Methode aus.


0

Im ersten Fall rufen Sie nur die run()Methode der Objekte r1und auf r2.

Im zweiten Fall erstellen Sie tatsächlich 2 neue Threads!

start()werde irgendwann anrufen run()!


7
Tatsächlich ruft start () run () nicht auf: Wenn dies der Fall ist, wird die run () -Methode von demselben Thread ausgeführt, der start () aufgerufen hat. Start () erstellt einen Thread, der die Methode run () aufruft.
Bruno Reis

0

Ausführungsmethode: - ist eine abstrakte Methode, die ursprünglich in der Runnable-Schnittstelle erstellt und in der Thread-Klasse sowie in Thread-Unterklassen (da Thread Runnable in seinem Quellcode implementiert) und anderen implementierenden Klassen der Runnable-Schnittstelle überschrieben wird. - Es wird verwendet, um den Thread (ausführbares Objekt) mit der Aufgabe zu laden, die er ausführen soll. Sie überschreiben ihn also, um diese Aufgabe zu schreiben.

Startmethode: - ist in der Thread-Klasse definiert. Wenn die start-Methode für ein Thread-Objekt 1 aufgerufen wird , ruft sie die intern native (nonjava) Methode mit dem Namen start0 () auf. Methode.

start0 (); Methode: ist für die geringe Verarbeitung verantwortlich (Stapelerstellung für einen Thread und Zuweisen des Threads in der Prozessorwarteschlange). Zu diesem Zeitpunkt befindet sich ein Thread im Status "Bereit / Ausführbar".

2- Zu einem Zeitpunkt, an dem der Thread-Scheduler entscheidet, dass ein Thread in einen Prozessorkern eintritt, der der Run-Methode (Thread-Priorität sowie OS-Scheduling-Algorithmus) entspricht, wird die Run-Methode für das Runnable-Objekt aufgerufen (unabhängig davon, ob es sich um das aktuelle Runnable-Thread-Objekt oder das übergebene Runnable-Objekt handelt an den Thread-Konstruktor) hier tritt ein Thread in einen laufenden Zustand ein und beginnt mit der Ausführung seiner Aufgabe (Ausführungsmethode)


-2

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.


2
Das Aufrufen von "run ()" ist keine Möglichkeit, Thread-Programme zu erstellen. Es gibt nur einen Weg.
Marquis von Lorne

-2

Start () -Methodenaufruf Run Override-Methode der erweiterten Thread-Klasse und Runnable implementiert die Schnittstelle.

Durch Aufrufen von run () wird jedoch nach der run-Methode gesucht. Wenn jedoch eine Klasse die Runnable-Schnittstelle implementiert, wird die run () - Override-Methode von Runnable aufgerufen.

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

`

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.