Jaka jest różnica między Thread start () a Runnable run ()

224

Powiedzmy, że mamy te dwa Runnable:

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

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

Jaka jest różnica między tym:

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

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

I to:

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();
}
Ori Popowski
źródło

Odpowiedzi:

309

Pierwszy przykład: brak wielu wątków. Oba są wykonywane w jednym (istniejącym) wątku. Brak tworzenia wątków.

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

r1i r2są tylko dwoma różnymi obiektami klas, które implementują Runnableinterfejs i tym samym implementują run()metodę. Kiedy dzwonisz r1.run(), wykonujesz go w bieżącym wątku.

Drugi przykład: dwa oddzielne wątki.

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

t1i t2są obiektami klasy Thread. Po wywołaniu t1.start()rozpoczyna nowy wątek i wywołuje run()metodę r1wewnętrzną w celu wykonania go w tym nowym wątku.

Bhesh Gurung
źródło
5
Couuld Uważam, że zanim wywołamy Thread # start (), nic tak naprawdę nie dzieje się z wątkiem OS? To tylko obiekt java.
Jaskey,
4
Zgadza się z dokumentacją. Sprawdź kod inicjalizacji obiektu wątku, który jest zgodny z dokumentacją. Również w kodzie źródłowym start()jest to metoda, która wywołuje metodę natvie, która musi powodować, że rzeczy związane z wątkiem OS się zdarzają.
Bhesh Gurung
3
Dokumentacja konstruktora wątków jest tutaj . Źródło inicjowania obiektu wątku jest tutaj . start()źródło metody jest tutaj .
Bhesh Gurung
92

Jeśli wywołujesz run()bezpośrednio, jest on wykonywany w wątku wywołującym, tak jak każde inne wywołanie metody. Thread.start()jest wymagane do utworzenia nowego wątku, tak aby runmetoda runnable była wykonywana równolegle.

Mike Daniels
źródło
2
W Hotspot JVM istnieje bezpośrednie mapowanie między wątkiem Java a rodzimym. Thread.start()wywołanie powoduje przeniesienie stanu wątku z nowego stanu do stanu Runnable . Runnable nie oznacza, że ​​wątek jest uruchomiony. Po zainicjowaniu wątku macierzystego wątek macierzysty wywołuje run()metodę w wątku Java, co powoduje zmianę stanu wątku z Runnable na Running . Po zakończeniu wątku wszystkie zasoby dla wątku rodzimego i Java zostają zwolnione.
przeeksponowanie
@overexchange Gdzie mogę znaleźć materiał na temat zmiany stanu.
twlkyao
73

Różnica polega na tym, że Thread.start()uruchamia wątek, który wywołuje run()metodę, a Runnable.run()tylko wywołuje run()metodę w bieżącym wątku.

Markiz Lorne
źródło
35

Różnicą jest to, że gdy program wywołuje start()metodzie nowy wątek jest tworzony i wewnątrz kod run()jest wykonywany w nowym wątku natomiast jeśli wywołanie run()metody bezpośrednio żaden nowy wątek zostanie utworzony i kod wewnątrz run()będzie wykonać w bieżącym wątku bezpośrednio.

Kolejna różnica między start()i run()w wątku Java jest to, że nie można nazwać start()dwukrotnie. Po uruchomieniu drugie start()wywołanie zostanie wygenerowane IllegalStateExceptionw Javie, podczas gdy można wywołać run()metodę kilka razy, ponieważ jest to zwykła metoda.

Jaimin Patel
źródło
21

W rzeczywistości Thread.start()tworzy nowy wątek i ma własny scenariusz wykonania.

Thread.start()wywołuje run()metodę asynchronicznie, co zmienia stan nowego wątku na Runnable.

Ale Thread.run()nie tworzy żadnego nowego wątku. Zamiast tego synchronicznie wykonuje metodę uruchamiania w bieżącym bieżącym wątku.

Jeśli używasz Thread.run(), to w ogóle nie używasz funkcji wielowątkowości.

aditya
źródło
8

invoke run()wykonuje się w wątku wywołującym, jak każde inne wywołanie metody. podczas gdy Thread.start()tworzy nowy wątek. wywoływanie run()to błąd programowy.

Narendra Jaggi
źródło
7

Jeśli zrobisz to run()w metodzie głównej, wątek metody głównej wywoła tę runmetodę zamiast wątku, który chcesz uruchomić.

start()Metoda tworzy nowy wątek, dla którego run()metoda musi być zrobione

Rohith
źródło
„Główna metoda” nie ma z tym nic wspólnego.
Markiz Lorne
3
@EJP przez mainpisarza oznaczało metodę wywoływania. Jego odpowiedź jest całkiem dobra. +1 ;-)
dom_beau
1
@dom_beau Jeśli to miał na myśli, powinien to powiedzieć. To, co powiedział, było nieprawidłowe. W tej odpowiedzi nie ma nic „całkiem dobrego”. To tylko zmieszany bałagan.
Markiz Lorne
5

t.start() to metoda zapewniana przez bibliotekę do wywoływania kodu, gdy potrzebny jest nowy wątek.

r.run()Jest to metoda, która Ci przewidywać, że biblioteka zadzwonić w nowym wątku.


Większość z tych odpowiedzi nie ma szerszego obrazu, co oznacza, że ​​jeśli chodzi o język Java, nie ma większej różnicy między żadnymi innymi metodami t.start()i r.run()pomiędzy nimi.

Obie są tylko metodami. Oba działają w wątku, który je wywołał . Obaj robią wszystko, do czego zostali zakodowani, a potem obaj wracają, wciąż w tym samym wątku, do swoich rozmówców.

Największą różnicą jest to, że większość kodu za t.start()to natywny kod, podczas gdy w większości przypadków kod r.run()będzie czysta Java. Ale to nie jest duża różnica. Kod to kod. Natywny kod jest trudniejszy do znalezienia i trudniejszy do zrozumienia, kiedy go znajdziesz, ale nadal jest to tylko kod, który mówi komputerowi, co ma robić.

Co więc robi t.start()?

Tworzy nowy natywny wątek, organizuje wywołanie tego wątku t.run(), a następnie informuje system operacyjny, aby zezwolił na uruchomienie nowego wątku. Potem wraca.

I co r.run()zrobić?

Zabawne jest to, że osoba zadająca to pytanie to osoba, która je napisała . r.run()robi wszystko , co Ty (tj. programista, który to napisał) zaprojektował.

Solomon Slow
źródło
4

Thread.start()kod rejestruje wątek w programie planującym, a program planujący wywołuje run()metodę. Także Threadklasa Runnablejest, podczas gdy jest interfejsem.

CHANDRAHAS
źródło
3

Punkty, które zrobili członkowie są w porządku, więc chcę tylko coś dodać. Chodzi o to, że JAVA nie obsługuje wielokrotnego dziedziczenia. Ale co jest, jeśli chcesz wyprowadzić klasę B z innej klasy A, ale możesz wyprowadzić tylko z jednej klasy. Problem polega teraz na tym, jak „wyprowadzić” z obu klas: A i Thread. Dlatego możesz użyć interfejsu Runnable.

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

public class B extends A implements Runnable{...
pommoisel
źródło
ładne wyjaśnienie metody run () za pomocą przykładu o Runnable - interfejsie i Thread - klasie
Pinky Walve
1

Jeśli bezpośrednio wywołujesz run()metodę, nie używasz funkcji wielowątkowości, ponieważ run()metoda jest wykonywana jako część wątku wywołującego.

Jeśli wywołasz start()metodę na wątku, Java Virtual Machine wywoła metodę run (), a dwa wątki będą działać jednocześnie - bieżący wątek ( main()w twoim przykładzie) i inny wątek (Runnable r1w twoim przykładzie).

Spójrz na kod źródłowy start()metody w klasie 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();

W powyższym kodzie nie można zobaczyć wywołania run()metody

private native void start0()odpowiada za wywołanie run()metody. JVM wykonuje tę natywną metodę.

Ravindra babu
źródło
0

W pierwszym przypadku po prostu wywołujesz run()metodę obiektów r1i r2.

W drugim przypadku tworzysz 2 nowe wątki!

start()zadzwoni run()w pewnym momencie!

Marsellus Wallace
źródło
7
W rzeczywistości start () nie wywołuje run (): gdyby tak było, wówczas metoda run () byłaby wykonywana przez ten sam wątek, który wywołał start (). Rozpocznie się od utworzenia wątku, który wywoła metodę run ().
Bruno Reis,
0

metoda run: - jest metodą abstrakcyjną utworzoną pierwotnie w interfejsie Runnable i nadpisaną w klasie Thread oraz podklasach Thread (As Thread implementuje Runnable w kodzie źródłowym) i wszelkich innych klasach implementujących Runnable. - Służy do załadowania wątku (obiektu wykonalnego) z zadaniem, które ma wykonać, więc przesłonisz go, aby napisać to zadanie.

metoda początkowa: - jest zdefiniowana w klasie wątków. Kiedy metoda start jest wywoływana na obiekcie wątku 1- , wywołuje wewnętrznie rodzimą metodę (nonjava) o nazwie start0 (); metoda.

start0 (); Metoda: odpowiada za niskie przetwarzanie (tworzenie stosu dla wątku i przydzielanie wątku w kolejce procesora). W tym momencie mamy wątek w stanie Gotowe / Uruchomione.

2- W momencie, gdy program planujący wątek zdecyduje, że wątek wejdzie w rdzeń procesora zgodnie z (priorytet wątku, a także algorytm planowania systemu operacyjnego), na obiekcie Runnable zostaje wywołana metoda uruchamiania (niezależnie od tego, czy jest to bieżący obiekt Thread Runna, czy przekazany obiekt Runnable do konstruktora wątków) tutaj wątek przechodzi w stan Uruchomiony i rozpoczyna wykonywanie swojego zadania (metoda uruchamiania)

Esraa Salama
źródło
-2

Oddzielne metody start () i run () w klasie Thread zapewniają dwa sposoby tworzenia programów wątkowych. Metoda start () rozpoczyna wykonywanie nowego wątku i wywołuje metodę run (). Metoda start () zwraca natychmiast, a nowy wątek normalnie kontynuuje działanie, aż do powrotu metody run ().

Metoda run () klasy Thread nic nie robi, więc podklasy powinny przesłonić metodę kodem do wykonania w drugim wątku. Jeśli instancja wątku jest tworzona za pomocą argumentu Runnable, metoda run () wątku wykonuje zamiast tego metodę run () obiektu Runnable w nowym wątku.

W zależności od charakteru programu wątkowego bezpośrednie wywołanie metody Thread run () może dać takie same wyniki jak wywołanie za pomocą metody start (), ale w tym drugim przypadku kod jest faktycznie wykonywany w nowym wątku.

gtzinos
źródło
2
Wywołanie `run () 'nie jest sposobem na tworzenie programów wątkowych. Jest tylko jeden sposób.
Markiz Lorne
-2

Wywołanie metody Start () metoda przesłonięcia metody klasy rozszerzonej wątku i interfejsu Runnable implementuje interfejs.

Ale wywołując metodę run (), szuka metody run, ale jeśli klasa implementuje interfejs Runnable, wówczas wywołuje metodę run () przesłaniającą metodę Runnable.

dawny.:

`

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

`

ankit
źródło