Quando chiameresti thread.run () di java invece di thread.start ()?


109

Quando chiameresti Java thread.run()invece di thread.start()?


47
Quando sono il metodo thread.start ()? :)
Bill the Lizard

3
@blank, la risposta è semplicemente: t.run()quando si desidera eseguire tl'attività di sul thread corrente e t.start()quando si desidera eseguire tl'attività di sul thread tstesso. O stai chiedendo casi d'uso reali?
Pacerier

2
Quando sei un idiota e vuoi passare un'ora a eseguire il debug del codice multithread solo per rendersi conto in seguito che avresti dovuto chiamare start()! Come me ... Questo metodo non dovrebbe essere pubblico!
Pierre Henry,

Risposte:


113

Potresti voler chiamare run () in un particolare unit test che riguarda strettamente la funzionalità e non la concorrenza.


95

Mai. Chiamare run () direttamente esegue semplicemente il codice in modo sincrono (nello stesso thread), proprio come una normale chiamata di metodo.


25
"Mai" è un po 'troppo assoluto. Forse non vuoi sempre un nuovo thread ed esegui ancora il codice?
Tomalak

4
Forse, ma in quel caso sarebbe inutilmente dispendioso creare un nuovo Thread solo per chiamare il metodo run (). È meglio creare un impianto Runnable e eseguirlo in-thread o costruire e iniziare un nuovo thread con esso.
Scott Bale

1
Sto solo rivisitando ... se mai, perché il metodo è pubblico?
vuoto

4
È pubblico perché Thread implementa Runnable. È possibile creare una sottoclasse Thread e sovrascrivere run (), che ha lo stesso effetto di mettere il codice in un Runnable e passarlo al costruttore Thread. Tuttavia, è meglio usare un oggetto Runnable separato, poiché ciò ti lascia più flessibilità (come passarlo a un Executor, ecc.).
Adam Crume

2
Vorrei fare un esempio concreto con cui sto lavorando: ho un programma che può essere eseguito come GUI o dalla riga di comando. Nel caso della GUI, voglio che l'oggetto che fa il lavoro pesante venga eseguito su un thread separato e invii gli aggiornamenti alla GUI. Nella modalità riga di comando, non ho bisogno di quel thread separato.
Edward Falk,

27

Preso dalle domande frequenti sui thread Java in stile codice :

D: Qual è la differenza tra i metodi start () e run () di un thread?

R: I metodi separati start () e run () nella classe Thread forniscono due modi per creare programmi in thread. Il metodo start () avvia l'esecuzione del nuovo thread e chiama il metodo run (). Il metodo start () ritorna immediatamente e il nuovo thread normalmente continua finché non ritorna 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 programma con thread, chiamare direttamente il metodo run () di Thread 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.


thread's run() method executes the run() method of the Runnable object in the new thread instead.Non è vero (o almeno il mio codice sorgente Java 8 dice il contrario), ma sfortunatamente il collegamento sembra interrotto, quindi riporto l'errore qui invece.
kajacx

1
@ Tomalak, questo non risponde alla domanda posta. La domanda non è chiedere la differenza, ma chiedere i casi d'uso in cui chiameremo thread.run()invece di thread.start().
Pacerier

24

L'esecuzione thread.run()non crea una nuova Threadin cui il tuo codice viene eseguito. Esegue semplicemente il codice nel Thread corrente da cui thread.run()viene richiamato il codice.

L'esecuzione thread.start()crea un nuovo thread a livello di sistema operativo in cui il run()metodo viene chiamato.

In sostanza:

Programmazione a thread singolo → Richiamo diretto del run()metodo

Programmazione multi thread → Richiamo del start()metodo

Inoltre, come altri hanno già detto, "testing" sembra essere l'unico caso consigliabile in cui puoi invocare run()direttamente dal tuo codice.


13

Questo è già stato accennato, ma solo per essere chiari: creare un nuovo oggetto Thread solo per chiamare il suo metodo run () è inutilmente costoso e dovrebbe essere una grande bandiera rossa. Sarebbe un disegno molto meglio, più disaccoppiato per creare un impl Runnable e (a) chiamata è di metodo run () direttamente, se questo è il comportamento desiderato, oppure (b) la costruzione di un nuovo thread con quella Runnable e avviare la discussione.

Meglio ancora, per un ulteriore disaccoppiamento, controlla l' Executorinterfaccia e il framework in JDK 5 e versioni successive. Ciò consente, in poche parole, di separare l'esecuzione dell'attività (l'istanza Runnable) da come dell'attività viene eseguita (l'implementazione dell'Executor, che potrebbe eseguire il Runnable nel Thread corrente, in un nuovo Thread, utilizzando un Thread esistente da un pool, e quant'altro).


9

Chiama thread.start(), chiamerà a sua volta thread.run(). Non riesco a pensare a un caso in cui vorresti bypassare thread.start()e andare direttamente athread.run()


3
Durante il test è l'unico caso legittimo a cui riesco a pensare. Altrimenti, il contenuto di run () dovrebbe trovarsi in un metodo separato che viene chiamato da run o con altri mezzi.
Bill the Lizard

9

I metodi separati start()e run()nella classe Thread forniscono due modi per creare programmi in thread. Il start()metodo avvia l'esecuzione del nuovo thread e chiama il run()metodo. Il start()metodo ritorna immediatamente e il nuovo thread normalmente continua finché il run()metodo non ritorna.

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

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

riferimento


Come la risposta di Tomalak !! Se hai fatto riferimento da qualche posto, per favore menzionalo !!
Barry

The start() method returns immediately and the new thread normally continues until the run() method returns.Se start()ritorna immediatamente come run()mai il continua a funzionare dato che è stato chiamato se stesso dastart()
KNU

7

Se la domanda era: "perché viene chiamato il metodo di avvio del thread invece di eseguire direttamente il metodo", ho risposto con un codice di esempio di seguito. Spero che questo chiarisca. Nell'esempio seguente:

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

    }
}

5

Quando vuoi che venga eseguito in modo sincrono. Chiamare il metodo run non ti darà effettivamente il multi-threading. Il metodo start crea un nuovo thread che chiama il metodo run.


3

Se vuoi eseguire il contenuto di run () come faresti con qualsiasi altro metodo. Non per iniziare una discussione, ovviamente.


3

Supponendo che si conosca l'avvio e l'utilizzo del metodo di esecuzione, ovvero sincrono e asincrono; Il metodo run può essere utilizzato solo per testare la funzionalità.

Inoltre, in alcune circostanze, la stessa classe di thread può essere utilizzata in due luoghi diversi con requisiti di funzionalità di sincronizzazione e asincronia avendo due oggetti diversi con il proprio metodo di esecuzione e il metodo di avvio dell'altro che vengono richiamati.


2

Almeno nella JVM 1.6., C'è un po 'di controllo ed esecuzione è chiamato in modo nativo:

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

2

Solo una nota agli ottimi commenti sopra: a volte scrivi un codice multi-thread che usa il metodo "start" per eseguire thread diversi. Troverai molto più facile se usi "run" (invece di "start) per il debug poiché rende il codice da eseguire in modo sincrono e il debug è molto più semplice.


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

Ciao Frnz, controlla ed esegui l'esempio sopra per capire chiaramente la prima esecuzione con t1.start () e vedere hashcode e la prossima volta con t1.run () e chk hashcodes
Avatar Girase

Dov'è la tua domanda?
Amen Jlili
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.