Quando você chamaria thread.run () de java em vez de thread.start ()?

109

Quando você chamaria o Java em thread.run()vez de thread.start()?

em branco
fonte
47
Quando sou o método thread.start ()? :)
Bill the Lizard
3
@blank, a resposta é simples: t.run()quando você deseja executar ta tarefa no thread atual e t.start()quando deseja executar ta tarefa no tpróprio thread . Ou você está pedindo casos de uso reais?
Pacerier
2
Quando você é um idiota e quer passar uma hora depurando código multithread apenas para perceber mais tarde que deveria apenas ter chamado start()! Como eu ... Este método não deve ser público!
Pierre Henry
Consulte também stackoverflow.com/questions/2674174/…
Radiodef

Respostas:

113

Você pode querer chamar run () em um teste de unidade específico que se preocupa estritamente com a funcionalidade e não com a simultaneidade.

Paul Croarkin
fonte
95

Nunca. Chamar run () diretamente apenas executa o código de forma síncrona (no mesmo thread), assim como uma chamada de método normal.

Adam Crume
fonte
25
"Nunca" é um pouco absoluto demais. Talvez nem sempre queira um novo thread e ainda execute o código?
Tomalak
4
Talvez, mas nesse caso seria um desperdício desnecessário criar um novo Thread apenas para chamar o método run (). Melhor criar um impl Runnable e executar esse in-thread ou construir e iniciar um novo Thread com ele.
Scott Bale
1
Apenas revisitando ... se nunca, por que o método é público?
branco
4
É público porque Thread implementa Runnable. Você pode criar uma subclasse de Thread e substituir run (), que tem o mesmo efeito de colocar seu código em um Runnable e passá-lo para o construtor Thread. É melhor prática usar um objeto Runnable separado, pois isso deixa você mais flexibilidade (como passá-lo para um Executor, etc.).
Adam Crume
2
Deixe-me dar um exemplo concreto com o qual estou trabalhando no momento: tenho um programa que pode ser executado como uma interface gráfica do usuário ou a partir da linha de comando. No caso da GUI, quero que o objeto que faz o trabalho pesado seja executado em um thread separado e envie atualizações para a GUI. No modo de linha de comando, não preciso desse segmento separado.
Edward Falk
27

Retirado do FAQ dos threads de estilo de código Java :

P: Qual é a diferença entre os métodos start () e run () de um thread?

R: Os métodos separados start () e run () na classe Thread fornecem duas maneiras de criar programas encadeados. O método start () inicia a execução da nova thread e chama o método run (). O método start () retorna imediatamente e a nova thread normalmente continua até que o método run () retorne.

O método run () da classe Thread não faz nada, então as subclasses devem sobrescrever o método com o código a ser executado no segundo thread. Se um Thread for instanciado com um argumento Runnable, o método run () do thread executa o método run () do objeto Runnable no novo thread.

Dependendo da natureza do seu programa encadeado, chamar o método Thread run () diretamente pode dar a mesma saída que chamar por meio do método start (), mas no último caso o código é realmente executado em um novo encadeamento.

Tomalak
fonte
thread's run() method executes the run() method of the Runnable object in the new thread instead.Isso não é verdade (ou pelo menos meu código-fonte Java 8 diz o contrário), mas infelizmente o link parece quebrado, então eu relato o erro aqui.
kajacx
1
@Tomalak, Isso não responde à pergunta feita. A questão não é perguntar sobre a diferença, mas sobre os casos de uso pelos quais chamaremos em thread.run()vez de thread.start().
Pacerier
24

A execução thread.run()não cria um novo Threadno qual seu código é executado. Ele apenas executa o código no Thread atual a partir do qual o thread.run()código é invocado.

A execução thread.start()cria um novo thread de nível de sistema operacional em que o run()método é chamado.

Em essência:

Programação Single Threaded → Chamando diretamente o run()método

Programação Multi Threaded → Chamando o start()método

Além disso, como outros mencionaram, 'teste' parece ser o único caso aconselhável em que você pode invocar run()diretamente do seu código.

Mahendra Liya
fonte
13

Isso já foi mencionado, mas só para ficar claro: criar um novo objeto Thread apenas para chamar seu método run () é desnecessariamente caro e deve ser um grande sinal de alerta. Seria um design muito melhor e mais desacoplado criar um Runnable impl e (a) chamar seu método run () diretamente se esse for o comportamento desejado, ou (b) construir um novo Thread com esse Runnable e iniciar o Thread.

Melhor ainda, para ainda mais desacoplamento, verifique a Executorinterface e a estrutura no JDK 5 e mais recente. Isso permite a você, em poucas palavras, desacoplar a execução da tarefa (a instância Runnable) de como ela é executada (a implementação do Executor, que pode executar o Runnable no Thread atual, em um novo Thread, usando um Thread existente de um pool, e o que não).

Scott Bale
fonte
9

Ligue thread.start(), ele por sua vez ligará thread.run(). Não consigo pensar em um caso em que você gostaria de contornar thread.start()e ir diretamente parathread.run()

Chris Ballance
fonte
3
Durante o teste, é o único caso legítimo em que consigo pensar. Caso contrário, o conteúdo de run () deve estar em um método separado que é chamado por run ou por outros meios.
Bill the Lizard
9

Os métodos separados start()e run()na classe Thread fornecem duas maneiras de criar programas encadeados. O start()método inicia a execução da nova thread e chama o run()método. O start()método retorna imediatamente e o novo thread normalmente continua até que o run()método retorne.

O run()método da classe Thread não faz nada, então as subclasses devem sobrescrever o método com o código a ser executado no segundo thread. Se um Thread for instanciado com um argumento Runnable, o run()método do thread executa o run()método do objeto Runnable no novo thread.

Dependendo da natureza do seu programa encadeado, chamar o run()método Thread diretamente pode dar a mesma saída que chamar por meio do start()método, mas no último caso o código é realmente executado em um novo encadeamento.

referência

alok
fonte
O mesmo que a resposta de Tomalak !! Se você fez referência de algum lugar, por favor mencione isso !!
Barry,
The start() method returns immediately and the new thread normally continues until the run() method returns.Se start()retornar imediatamente, como é que o run()continua a funcionar, visto que foi chamado destart()
KNU
7

Se a pergunta era - "por que o método de início de thread é chamado em vez do método de execução diretamente", respondi com um código de exemplo abaixo. Espero que isso esclareça. No exemplo abaixo:

/*
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
fonte
5

Quando você quiser que ele seja executado de forma síncrona. Chamar o método run não dará a você multithreading. O método start cria uma nova thread que chama o método run.

Brian
fonte
3

Se você deseja executar o conteúdo de run () como faria com qualquer outro método. Para não começar um tópico, é claro.


fonte
3

Supondo que você saiba o uso do método de início e execução, ou seja, síncrono vs. assíncrono; O método run pode ser usado apenas para testar a funcionalidade.

Além disso, em algumas circunstâncias, a mesma classe de thread pode ser usada em dois lugares diferentes com requisitos de funcionalidade de sincronização e assincronização, tendo dois objetos diferentes com um método de execução e outro método de início sendo invocado.

Salman Kasbati
fonte
2

Pelo menos no JVM 1.6., Há um pouco de verificação e a execução é chamada nativamente:

 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.
fonte
2

Apenas uma observação aos ótimos comentários acima: às vezes você escreve um código multi-thread que usa o método "start" para executar diferentes threads. Você verá que é muito mais fácil usar "run" (em vez de "start) para depuração, pois isso torna o código executado de maneira síncrona e a depuração é muito mais fácil.

msamadi
fonte
-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
fonte
Olá Frnz, Verifique e execute o exemplo acima para entender claramente, primeiro execute com t1.start () e veja o hashcode e da próxima vez com t1.run () e chk hashcodes
Avatar Girase
Onde está sua pergunta?
Amen Jlili de