Dúvida em run() e start()

[code]public class Threads3 implements Runnable{
public void run(){
System.out.println(“running”);
}

public static void main (String args[]){
	Thread t = new Thread( new Threads3() );

	t.start();
	t.run();
	t.run();
}

}[/code]

Por que existem vezes em que o código acima imprime apenas uma vez “running”? Não era para imprimir sempre 3 vezes?

Obrigado!

Note que o run sendo chamado é do objeto “t”, que não possue uma implementação de “run”. Mas quando “t” chama o método “start”, o método “run” do objeto Threads3 é chamado, e aí escreve “running” na tela.

Como assim Douglas? O Objeto ‘t’ possui sim a implementação de run()!!! O que eu estou questionando é que, às vezes, o código imprime 3 vezes “running” e, outras vezes, imprime apenas uma vez. Para mim, deveria imprimir SEMPRE 3 vezes!!! Essa é minha pergunta!

Hum… foi falha minha. Eu pensei errado pelo seguinte. No código que você passou, quem está implementando o método “run” é a classe Threads3. Este método é chamado quando você chama “start” em “t”. Quando você chama “t.run()”, t está chamando o método “run” de Threads3.

Bom, quanto a sua dúvida, eu fiz um teste aqui e ta escrevendo Running sempre 3 vezes. Desculpe ae se não fui de muita ajuda.

De boa Douglas! Então está saindo sempre 3 vezes no seu? :shock: Estranho… Acabei de refazer o teste aqui. No meu, as vezes sai apenas uma vez também. Vamos esperar para ver se alguém sabe o que está acontecendo. :wink:

bem vamos lá com o run eh um metodo como qualquer outro, que vc está chamando e o start() vc faz diz a jvm que usa thread está pronta a executar, cabe a jvm executar ou nao. lembre-se com threads nao há garantias. veja se esse meu post ajuda.

abracos

Cara, quando você usa o método start, ele não é garantido que a nova thread que você iniciou vai ser executada na hora.
Existem claramente mais de uma possibilidade neste código.

Primeiro: O start que você usou na thread não executa uma nova thread no exato momento, executando primeiro as 2 linhas de código seguintes que são os 2 run’s, printando 2 vezes na tela a sua mensagem. E em seguida, aquele método start que você chamou antes executa depois, resultando em 3 mensagens.

Segundo: O start pode executar a thread antes dos métodos run que você chamou(algo só aparentemente mais “normal”), printando na tela apenas 1 vez a sua mensagem. As outras 2 chamadas do método run são inúteis, pois uma vez que o método start é executado e completado a sua execução a thread muda para o estado TERMINATED, onde essas chamadas de run não são válidas, não se pode usar uma thread no estado TERMINATED.

Faça testes com o método da classe Thread getState() e veja os 6 estados possíveis da Thread: NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING e TERMINATED.

Não faz o menor sentido.

Pelas regras, deve sempre ser escrito running três vezes. Não existe isso de que se uma thread morrer os comandos após a chamada dessa thread não serem executados. Tudo sempre é executado, a não ser que haja um comando como esse na main

Thread.currentThread().setDaemon(true);

ou um wait ou algo do tipo.
Eu acho (e agora estou especulando) que foi algum problema do SO em si, alguma inconsistência.

Ele está certo. O método start da classe thread faz o seguinte:

a) Se a thread está associada a um Runnable, dispara a thread no método run() desse runnable;
b) Caso contrário, dispara o método run() de si mesmo.

No caso do seu código, a Thread t foi criada diretamente da classe Thread e, portanto, não tem o método run() implementado. Quando você dispara pelo start, cai na condição a), e o método run() de Threads3, que está associada, é disparado.

Quando você chama o run(), você está chamando o run() de Thread, que não está implementado.

Mas a minha dica é a seguinte.

   1. public class Threads3 implements Runnable{  
   2.     public void run(){  
   3.         System.out.println("running");  
   4.     }  
   5.   
   6.     public static void main (String args[]){  
   7.         Thread t = new Thread( new Threads3() );  
   8.   
   9.         t.start();  
  10.         t.run();  
  11.         t.run();  
  12.     }  
  13. }  

este teu codigo é suspeito , !!! :slight_smile: :slight_smile: :slight_smile: :smiley: :smiley: , ninguem entendi o porque destes dois " run " ai,

Ele está certo. O método start da classe thread faz o seguinte:

a) Se a thread está associada a um Runnable, dispara a thread no método run() desse runnable;
b) Caso contrário, dispara o método run() de si mesmo.

No caso do seu código, a Thread t foi criada diretamente da classe Thread e, portanto, não tem o método run() implementado. Quando você dispara pelo start, cai na condição a), e o método run() de Threads3, que está associada, é disparado.

Quando você chama o run(), você está chamando o run() de Thread, que não está implementado.[/quote]]]

ViniGodoy, por esse seu raciocínio, não era para imprimir sempre apenas uma vez “running” então? Você afirmou que “Quando você chama o run(), você está chamando o run() de Thread, que não está implementado” o que eu discordo. Eu sobreescrevi ele na minha classe Threads3. Porque ao fazer t.run(); não iria ser chamado esse run() que eu sobreescrevi? Cade o polimorfismo ai?

[quote=renamed]Não faz o menor sentido.

Pelas regras, deve sempre ser escrito running três vezes. Não existe isso de que se uma thread morrer os comandos após a chamada dessa thread não serem executados. Tudo sempre é executado, a não ser que haja um comando como esse na main

Thread.currentThread().setDaemon(true);

ou um wait ou algo do tipo.
Eu acho (e agora estou especulando) que foi algum problema do SO em si, alguma inconsistência.[/quote]

renamed, eu também acho que não tem essa de que, se a thread morrer, não se pode mais chamar o run(); O run é um método public qualquer. Ele pode ser chamado SEMPRE. O que não se pode chamar é o start() mais de uma vez, caso contrário, uma exceção é lançada. Mesmo após a thread terminar o método run(), não se pode executar o start novamente.

Agora, a minha dúvida persiste :frowning: Vc fez testes ae também renamed? O que está imprimindo?

Abraço!

Ah não, você tem razão. O que tem o comportamento que descrevi é mesmo o run. Veja a implementação do método run() da classe Thread:

    public void run() {
        if (target != null) {
            target.run();
        }
    }

Nesse caso, o código sempre imprimirá 3 vezes a palavra running.

Como você está fazendo para imprimir o dado? Está executando o java via console ou por alguma IDE?

Rodei aqui diversas vezes, e funcionou perfeitamente. Imprime 3 vezes a palavra Running.

[quote=TiagoTC]ViniGodoy, por esse seu raciocínio, não era para imprimir sempre apenas uma vez “running” então? Você afirmou que “Quando você chama o run(), você está chamando o run() de Thread, que não está implementado” o que eu discordo. Eu sobreescrevi ele na minha classe Threads3.
Porque ao fazer t.run(); não iria ser chamado esse run() que eu sobreescrevi? Cade o polimorfismo ai?[/quote]

Só um detalhe. O fato de executar o run não tem nada a ver com polimorfismo.

t é do tipo Thread, não do tipo Threads3. Ele não teria obrigação nenhuma de executar o seu run(), exceto pela forma como é implementado. Não é uma questão de polimorfismo. O polimorfismo só ocorreria se Threads3 fosse filho de thread, implementasse o método run(), e você criasse t como o tipo Threads3. Então, chamar o start() faria disparar o run() de Threads3, pois ele estaria sobrescrito na classe.

Estou no Linux. Faço “javac Threads3.java” para compilar e “java Threads3” para executar. Tudo na linha de comando mesmo. Aqui ou imprime 3 vezes “running” ou apenas uma vez…

[quote=ViniGodoy][quote=TiagoTC]ViniGodoy, por esse seu raciocínio, não era para imprimir sempre apenas uma vez “running” então? Você afirmou que “Quando você chama o run(), você está chamando o run() de Thread, que não está implementado” o que eu discordo. Eu sobreescrevi ele na minha classe Threads3.
Porque ao fazer t.run(); não iria ser chamado esse run() que eu sobreescrevi? Cade o polimorfismo ai?[/quote]

Só um detalhe. O fato de executar o run não tem nada a ver com polimorfismo.

t é do tipo Thread, não do tipo Threads3. Ele não teria obrigação nenhuma de executar o seu run(), exceto pela forma como é implementado. Não é uma questão de polimorfismo. O polimorfismo só ocorreria se Threads3 fosse filho de thread, implementasse o método run(), e você criasse t como o tipo Threads3. Então, chamar o start() faria disparar o run() de Threads3, pois ele estaria sobrescrito na classe.[/quote]

Humm, é verdade, eu havia esquecido que estava implementando Runnable e não estendendo de Thread. Vlw pela explicação! :thumbup:

Mas, voltando à pergunta inicial. Será que o fato de não estar exibindo sempre 3 vezes “running” aqui seja por algum problema na JVM ?

Me veio outra dúvida agora. Imagina que, ao dar o t.start(), a thread não comece a executar o run() imediatamente naquele momento. Então, os outros 2 códigos serão executados ( t.run() e t.run() ), imprimindo 2 vezes “running” na tela. E se a thread main chegar ao final do seu bloco sem a thread t ter começado sua execução? Então, neste caso, iria acabar imprimindo apenas 2 vezes “running”, não? Pode acontecer esse caso?

Só pode acontecer se a thread t for uma deamon thread. Caso contrário, ela mantém o programa vivo.

Estranho, imprimir uma vez nem sequer faz sentido, já que você tem duas chamadas a t.run(). Mesmo que não houvesse aquele start(), pelo menos 2 vezes teria que ser impresso.