Kiedy można wywołać funkcję thread.run () języka Java zamiast thread.start ()?

109

Kiedy nazwałbyś Java thread.run()zamiast thread.start()?

pusty
źródło
47
Kiedy jestem metodą thread.start ()? :)
Bill the Lizard
3
@blank, Odpowiedź jest prosta: t.run()kiedy chcesz uruchomić tzadanie w bieżącym wątku i t.start()kiedy chcesz uruchomić tzadanie w tsamym wątku . A może pytasz o rzeczywiste przypadki użycia?
Pacerier
2
Kiedy jesteś idiotą i chcesz spędzić godzinę na debugowaniu kodu wielowątkowego, aby później zdać sobie sprawę, że powinieneś był po prostu zadzwonić start()! Tak jak ja ... Ta metoda nie powinna być publiczna!
Pierre Henry

Odpowiedzi:

113

Możesz chcieć wywołać metodę run () w konkretnym teście jednostkowym, który dotyczy wyłącznie funkcjonalności, a nie współbieżności.

Paul Croarkin
źródło
95

Nigdy. Bezpośrednie wywołanie run () po prostu wykonuje kod synchronicznie (w tym samym wątku), tak jak zwykłe wywołanie metody.

Adam Crume
źródło
25
„Nigdy” jest zbyt bezwzględne. Może nie zawsze chcesz mieć nowy wątek i nadal wykonywać kod?
Tomalak
4
Może, ale w takim przypadku byłoby niepotrzebnie marnotrawstwem tworzenie nowego wątku tylko w celu wywołania metody run (). Lepiej jest utworzyć plik Impl Runnable i albo uruchomić go w wątku, albo skonstruować i rozpocząć z nim nowy wątek.
Scott Bale
1
Po prostu wracam ... jeśli nigdy, dlaczego metoda jest publiczna?
puste
4
Jest publiczna, ponieważ Thread implementuje Runnable. Możesz podklasować Thread i przesłonić run (), co ma taki sam efekt, jak umieszczenie kodu w Runnable i przekazanie go do konstruktora Thread. Lepszą praktyką jest jednak użycie oddzielnego obiektu Runnable, ponieważ daje to większą elastyczność (na przykład przekazywanie go do Executora itp.).
Adam Crume,
2
Podam konkretny przykład, z którym obecnie pracuję: Mam program, który można uruchomić jako GUI lub z wiersza poleceń. W przypadku GUI chcę, aby obiekt, który wykonuje ciężkie podnoszenie, działał w osobnym wątku i wysyłał aktualizacje do GUI. W trybie wiersza poleceń nie potrzebuję tego oddzielnego wątku.
Edward Falk
27

Zaczerpnięte z często zadawanych pytań dotyczących wątków Java Style Code :

P: Jaka jest różnica między metodami start () i run () wątku?

Odp .: Oddzielne metody start () i run () w klasie Thread zapewniają dwa sposoby tworzenia programów z wątkami. Metoda start () rozpoczyna wykonywanie nowego wątku i wywołuje metodę run (). Metoda start () zwraca natychmiastowo, a nowy wątek normalnie kontynuuje działanie do momentu 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 wystąpienie Thread jest tworzone z argumentem Runnable, metoda run () wątku wykonuje zamiast tego metodę run () obiektu Runnable w nowym wątku.

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

Tomalak
źródło
thread's run() method executes the run() method of the Runnable object in the new thread instead.To nieprawda (a przynajmniej mój kod źródłowy Java 8 mówi inaczej), ale niestety link wydaje się uszkodzony, więc zamiast tego zgłaszam błąd tutaj.
kajacx
1
@Tomalak, To nie odpowiada na zadane pytanie. Nie chodzi o różnicę, ale o przypadki użycia, w których thread.run()zamiast tego zadzwonimy thread.start().
Pacerier
24

Wykonywanie thread.run()nie tworzy nowego, Threadw którym kod zostanie wykonany. Po prostu wykonuje kod w bieżącym wątku, z którego thread.run()kod jest wywoływany.

Wykonanie thread.start()tworzy nowy wątek na poziomie systemu operacyjnego, w którym run()metoda jest wywoływana.

W istocie:

Programowanie jednowątkowe → Bezpośrednie wywołanie run()metody

Programowanie wielowątkowe → Wywołanie start()metody

Ponadto, jak wspomnieli inni, „testowanie” wydaje się być jedynym wskazanym przypadkiem, w którym można wywołać run()bezpośrednio z kodu.

Mahendra Liya
źródło
13

Wspomniano już o tym, ale dla jasności: tworzenie nowego obiektu Thread tylko w celu wywołania metody run () jest niepotrzebnie kosztowne i powinno być główną czerwoną flagą. Byłoby znacznie lepszym, bardziej odsprzężonym projektem, aby utworzyć Runnable impl i albo (a) wywołać jego metodę run () bezpośrednio, jeśli jest to pożądane zachowanie, albo (b) skonstruować nowy Thread z tym Runnable i uruchomić Thread.

Jeszcze lepiej, aby uzyskać jeszcze większe oddzielenie, sprawdź Executorinterfejs i framework w JDK 5 i nowszych. Pozwala to, w skrócie, oddzielić wykonanie zadania (wystąpienie Runnable) od sposobu jego wykonywania (implementacja Executor, która może wykonać Runnable w bieżącym wątku, w nowym wątku, używając istniejącego wątku z puli, i co innego).

Scott Bale
źródło
9

Zadzwoń thread.start(), to z kolei zadzwoni thread.run(). Nie mogę wymyślić przypadku, w którym chciałbyś ominąć thread.start()i przejść bezpośrednio dothread.run()

Chris Ballance
źródło
3
Podczas testów to jedyny uzasadniony przypadek, jaki przychodzi mi do głowy. W przeciwnym razie zawartość run () powinna znajdować się w oddzielnej metodzie wywoływanej przez funkcję run lub w inny sposób.
Bill the Lizard
9

Oddzielne metody start()i run()w klasie Thread zapewniają dwa sposoby tworzenia programów z wątkami. start()Metoda rozpoczyna realizację nowego wątku i wywołuje run()metodę. start()Metoda zwraca natychmiast i nowy wątek zazwyczaj trwa do run()powrotów metod.

Metoda klasy Thread run()nic nie robi, więc podklasy powinny przesłonić metodę kodem do wykonania w drugim wątku. Jeśli wystąpienie Thread jest tworzone z argumentem Runnable, run()metoda wątku wykonuje run()zamiast tego metodę obiektu Runnable w nowym wątku.

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

odniesienie

alok
źródło
To samo, co odpowiedź Tomalaka !! Jeśli odnosiłeś się z jakiegoś miejsca, wspomnij o tym !!
Barry
The start() method returns immediately and the new thread normally continues until the run() method returns.Jeśli start()wróci natychmiast, dlaczego run()nadal działa, biorąc pod uwagę, że został wywołany odstart()
KNU
7

Jeśli pytanie brzmiało - „dlaczego metoda uruchamiania wątku jest wywoływana zamiast bezpośrednio uruchamiania metody”, to odpowiadałem za pomocą przykładowego kodu poniżej. Mam nadzieję, że to wyjaśnia. W poniższym przykładzie:

/*
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
źródło
5

Kiedy chcesz, aby działał synchronicznie. Wywołanie metody run w rzeczywistości nie zapewni wielowątkowości. Metoda start tworzy nowy wątek, który wywołuje metodę run.

Brian
źródło
3

Jeśli chcesz wykonać zawartość run () tak, jak każdej innej metody. Oczywiście, żeby nie rozpoczynać wątku.


źródło
3

Zakładając, że znasz sposób użycia metody start and run, tj. Synchroniczna i asynchroniczna; run można użyć tylko do przetestowania funkcjonalności.

Ponadto w pewnych okolicznościach ta sama klasa wątku może być używana w dwóch różnych miejscach z wymaganiami dotyczącymi funkcji synchronizacji i asynchronizacji, mając dwa różne obiekty z jedną metodą uruchamiania i wywoływaną metodą startową innej.

Salman Kasbati
źródło
2

Przynajmniej w JVM 1.6. Jest trochę sprawdzania i uruchamiania nazywa się natywnie:

 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.
źródło
2

Tylko uwaga do powyższych świetnych komentarzy: czasami piszesz kod wielowątkowy, który używa metody "start" do uruchamiania różnych wątków. O wiele łatwiej będzie, jeśli użyjesz „run” (zamiast „start) do debugowania, ponieważ znacznie ułatwia to synchroniczne uruchamianie kodu i debugowanie.

msamadi
źródło
-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
źródło
Cześć Frnz, Sprawdź i uruchom powyższy przykład, aby jasno zrozumieć, że najpierw uruchom z t1.start () i zobacz hashcode, a następnym razem z t1.run () i chk hashcodes
Avatar Girase
Gdzie jest twoje pytanie
Amen Jlili