Qual è la differenza tra Thread start () e Runnable run ()


224

Supponiamo di avere questi due Runnable:

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

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

Quindi qual è la differenza tra questo:

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

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

E questo:

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

Risposte:


309

Primo esempio: nessun thread multiplo. Entrambi vengono eseguiti in thread singolo (esistente). Nessuna creazione di thread.

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

r1e r2sono solo due diversi oggetti di classi che implementano l' Runnableinterfaccia e quindi implementano il run()metodo. Quando chiami r1.run()lo stai eseguendo nel thread corrente.

Secondo esempio: due thread separati.

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

t1e t2sono oggetti della classe Thread. Quando chiami t1.start(), avvia un nuovo thread e chiama il run()metodo r1internamente per eseguirlo all'interno di quel nuovo thread.


5
Potrei considerare che prima di chiamare Thread # start (), non accade nulla di veramente relativo al thread os? È solo un oggetto Java.
Jaskey il

4
Questo è corretto secondo la documentazione. Controllare il codice di inizializzazione dell'oggetto thread, conforme alla documentazione. Anche nel codice sorgente, è il start(), che chiama un metodo natvie, che deve far accadere le cose relative al thread os.
Bhesh Gurung,

3
I documenti del costruttore del thread sono qui . La fonte di inizializzazione dell'oggetto thread è qui . start()la fonte del metodo è qui .
Bhesh Gurung,

92

Se invochi run()direttamente, viene eseguito sul thread chiamante, proprio come qualsiasi altra chiamata di metodo. Thread.start()è necessario per creare effettivamente un nuovo thread in modo che il runmetodo del runnable sia eseguito in parallelo.


2
In Hotspot JVM, esiste un mapping diretto tra thread Java e thread nativo. Thread.start()la chiamata fa spostare lo stato del thread dal nuovo stato allo stato Runnable . Runnable non significa che il thread è in esecuzione. Una volta inizializzato il thread nativo, il thread nativo richiama il run()metodo nel thread Java, che modifica lo stato del thread da Runnable a Running . Quando il thread termina, vengono rilasciate tutte le risorse sia per il thread nativo che Java.
Scambio eccessivo

@overexchange Dove posso trovare il materiale sul cambio di stato.
twlkyao,

73

La differenza è che Thread.start()avvia un thread che chiama il run()metodo, mentre Runnable.run()chiama semplicemente il run()metodo sul thread corrente.


35

La differenza è che quando il programma chiama il start()metodo, viene creato un nuovo thread e il codice all'interno run()viene eseguito nel nuovo thread mentre se si chiama il run()metodo direttamente non verrà creato alcun nuovo thread e il codice all'interno run()verrà eseguito direttamente nel thread corrente.

Un'altra differenza tra start()e run()nel thread Java è che non è possibile chiamare start()due volte. Una volta avviata, la seconda start()chiamata verrà lanciata IllegalStateExceptionin Java mentre è possibile chiamare il run()metodo più volte poiché è solo un metodo normale .


21

Thread.start()Crea effettivamente un nuovo thread e ha il suo scenario di esecuzione.

Thread.start()chiama il run()metodo in modo asincrono, che cambia lo stato del nuovo thread in Runnable.

Ma Thread.run()non crea alcun nuovo thread. Invece esegue il metodo di esecuzione nel thread corrente corrente in modo sincrono.

Se stai usando, Thread.run()non stai usando affatto le funzionalità del multi threading.


8

invoke run()è in esecuzione sul thread chiamante, come qualsiasi altra chiamata di metodo. mentre Thread.start()crea un nuovo thread. invocare run()è un bug programmatico.


7

Se lo fai run()nel metodo principale, il thread del metodo principale invocherà il runmetodo anziché il thread che devi eseguire.

Il start()metodo crea un nuovo thread e per il quale run()deve essere eseguito il metodo


Il "metodo principale" non ha nulla a che fare con esso.
Marchese di Lorne,

3
@EJP, per mainlo scrittore intendeva il metodo di chiamata. La sua risposta è abbastanza buona +1 ;-)
dom_beau

1
@dom_beau Se fosse quello che intendeva, avrebbe dovuto dirlo. Quello che ha detto era errato. Non c'è niente di "abbastanza buono" in questa risposta. È solo un casino confuso.
Marchese di Lorne,

5

t.start() è il metodo che la libreria fornisce al tuo codice per chiamare quando vuoi un nuovo thread.

r.run()è il metodo che si prevedono per la biblioteca per chiamare nel nuovo thread.


Alla maggior parte di queste risposte manca il quadro generale, ovvero che, per quanto riguarda il linguaggio Java, non c'è più differenza tra t.start()e di r.run()quanto non ci sia tra altri due metodi.

Sono entrambi solo metodi. Entrambi corrono nel thread che li ha chiamati . Entrambi fanno qualunque cosa sia stata programmata, e poi ritornano entrambi, sempre nello stesso thread, ai loro chiamanti.

La differenza più grande è che la maggior parte del codice per t.start()è codice nativo mentre, nella maggior parte dei casi, il codice per r.run()sarà puro Java. Ma non fa molta differenza. Il codice è codice. Il codice nativo è più difficile da trovare e più difficile da capire quando lo trovi, ma è ancora solo il codice che dice al computer cosa fare.

Quindi cosa fa t.start()?

Crea un nuovo thread nativo, organizza il richiamo di quel thread t.run()e quindi dice al sistema operativo di far funzionare il nuovo thread. Quindi ritorna.

E che cosa r.run()fare?

La cosa divertente è che la persona che pone questa domanda è la persona che l'ha scritta . r.run()fa qualunque cosa tu (cioè lo sviluppatore che l'ha scritto) lo abbia progettato per fare.


4

Thread.start()Il codice registra il thread con lo scheduler e lo scheduler chiama il run()metodo. Inoltre, Threadè class while Runnableè un'interfaccia.


3

I punti che i membri hanno sottolineato vanno bene, quindi voglio solo aggiungere qualcosa. Il fatto è che JAVA non supporta l'ereditarietà multipla. Ma cosa succede se vuoi derivare una classe B da un'altra classe A, ma puoi derivare solo da una classe. Il problema ora è come "derivare" da entrambe le classi: A e Thread. Pertanto è possibile utilizzare l'interfaccia eseguibile.

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

public class B extends A implements Runnable{...

bella spiegazione del metodo run () con l'aiuto di un esempio di Runnable - un'interfaccia e Thread - una classe
Pinky Walve,

1

Se si chiama direttamente il run()metodo, non si utilizza la funzione multi-thread poiché il run()metodo viene eseguito come parte del thread del chiamante.

Se si chiama start()metodo su Thread, Java Virtual Machine chiamerà il metodo run () e due thread verranno eseguiti contemporaneamente: Thread corrente ( main()nell'esempio) e Altro thread (Eseguibile r1nell'esempio).

Dai un'occhiata al codice sorgente del start()metodo in 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();

Nel codice sopra, non puoi vedere l'invocazione al run()metodo.

private native void start0()è responsabile del run()metodo di chiamata . JVM esegue questo metodo nativo.


0

Nel primo caso stai semplicemente invocando il run()metodo di r1er2 oggetti .

Nel secondo caso in realtà stai creando 2 nuovi thread!

start()chiamerà run()ad un certo punto!


7
In realtà, start () non chiamerà run (): in tal caso, il metodo run () verrebbe eseguito dallo stesso thread che chiamava start (). Ciò che start () farà è creare un thread che chiamerà il metodo run ().
Bruno Reis,

0

metodo di esecuzione: - è un metodo astratto originariamente creato nell'interfaccia Runnable e sovrascritto nella classe Thread e nelle sottoclassi Thread (poiché Thread implementa Runnable nel suo codice sorgente) e qualsiasi altra classe di implementazione dell'interfaccia Runnable. - Viene utilizzato per caricare il thread (oggetto eseguibile) con l'attività che si intende svolgere, quindi lo si sovrascrive per scrivere quell'attività.

metodo start: - è definito nella classe Thread. Quando il metodo start viene chiamato su un oggetto Thread 1 , chiama il metodo nativo interno (nonjava) chiamato start0 (); metodo.

start0 (); metodo: è responsabile della bassa elaborazione (creazione dello stack per un thread e allocazione del thread nella coda del processore) a questo punto abbiamo un thread nello stato Pronta / Eseguibile.

2- In un momento in cui l'utilità di pianificazione dei thread decide che un thread entra in un core del processore in base al quale viene eseguito il metodo di esecuzione (priorità del thread e algoritmo di pianificazione del sistema operativo) sull'oggetto Runnable (sia esso l'oggetto thread Runnable corrente o l'oggetto Runnable passato al costruttore del thread) qui un thread entra in uno stato Running e inizia a eseguire la sua attività (metodo run)


-2

I metodi start () ed run () separati nella classe Thread forniscono due modi per creare programmi thread. Il metodo start () avvia l'esecuzione del nuovo thread e chiama il metodo run (). Il metodo start () ritorna immediatamente e il nuovo thread continua normalmente fino a quando non viene restituito il metodo run ().

Il metodo run () della classe Thread non fa nulla, quindi le sottoclassi dovrebbero sovrascrivere il metodo con il codice da eseguire nel secondo thread. Se un thread viene istanziato con un argomento Runnable, il metodo run () del thread esegue invece il metodo run () dell'oggetto Runnable nel nuovo thread.

A seconda della natura del tuo programma thread, la chiamata diretta del metodo Thread run () può fornire lo stesso output della chiamata tramite il metodo start (), ma in quest'ultimo caso il codice viene effettivamente eseguito in un nuovo thread.


2
Chiamare `run () 'non è un modo per creare programmi thread. C'è solo un modo.
Marchese di Lorne,

-2

Il metodo Start () esegue il metodo di override della classe estesa Thread e dell'interfaccia degli attrezzi Runnable.

Ma chiamando run () cerca il metodo run ma se la classe implementa l'interfaccia Runnable, allora chiama run () sovrascrive il metodo 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 ");
    }
}

`

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.