Dúvida de Threads

7 respostas
M

Pessoal, alguém poderia me explicar por que a saída do programa abaixo é:
alou from MyThread
alou from MyThread
alou from MyRunnable

e não:
alou from MyThread
alou from MyRunnable
alou from MyRunnable

public class MyThread extends Thread {
	
	public MyThread() {
		super();
	}
	public MyThread(Runnable runnable) {
		super(runnable);
	}
	
	public void run() {
		System.out.println("alou from MyThread");
	}

	public static void main(String[] args) {
		new MyThread().start();
		new MyThread(new MyRunnable()).start();
		new Thread(new MyRunnable()).start();
	}
}

7 Respostas

M

Faltou postar o trecho da classe MyRunnable

class MyRunnable implements Runnable {
	public void run() {
		System.out.println("alou from MyRunnable");
	}
}
nilolima

Cara eu entedendo assim… olha só
Como a class MyThread sobrescreve o método run, o original da Class Thread não vai ser chamado. O métodod original de Thread, sim, chamaria o RUN do Runnable passado como parametro no construtor. Mas como vc sobrescreveu ele chama o run que vc criou.

Acho que é isso.
Boa sorte nos estudos para prova

M

Fala nilo,

obrigado por responder.
Mas olha só, de acordo com a API o método run() a ser executado é o da classe Runnable passado como parâmetro.

Por isso que eu achei estranho ter sido chamado a implementação do método run() da classe MyThread ao invés do método run() da classe MyRunnable.

Ah! só para complementar, eu abri o fonte da classe Thread e olha só como é a implementação do método run():

/**
     * If this thread was constructed using a separate 
     * <code>Runnable</code> run object, then that 
     * <code>Runnable</code> object's <code>run</code> method is called; 
     * otherwise, this method does nothing and returns. 
     * <p>
     * Subclasses of &lt;code&gt;Thread&lt;/code&gt; should override this method. 
     *
     * @see     java.lang.Thread#start()
     * @see     java.lang.Thread#stop()
     * @see     java.lang.Thread#Thread(java.lang.ThreadGroup, 
     *          java.lang.Runnable, java.lang.String)
     * @see     java.lang.Runnable#run()
     */
    public void run() {
	if (target != null) {
	    target.run();
	}
    }

sendo que o atributo target é setado no método init():

private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize) {
....
this.target = target;
...
}
nilolima

Sim,

Normal. Ele não chama o da class thread pq vc sobrescreveu o método. A implementação do método run da class thread é normal. Não vejo nada de estranho como target é um Runnable, se a referencia para terget não for nulla ele chama o run da target. Mas seu código nem chega nesa run pq a class MyThread sobrescreve o run, então ele chama o da class sobrescrita que num sabe da existencia de uma referencia para um Runnable.

Eu to achando isso normal.

O

boa questão!

só vale salientar que essa ordem

alou from MyThread
alou from MyThread
alou from MyRunnable

NÃO É GARANTIDA!

O que é garantido é termos:

2x: alou from MyThread
1x: alou from MyRunnable

B
new MyThread().start();
	[b]new MyThread(new MyRunnable()).start();[/b]
	new Thread(new MyRunnable()).start();

Na linha em negrito o start é do MyThread, e então ela pega o método run do MyThread mesmo. Ou seja, mesmo com a alteração no construtor, vc ainda está dando start no MyThread e não no MyRunnable.

Tente alterar o método run do MyThread para chamar o run do MyRunnable que vc passou como parametro no construtor.

t+

Daniel_Santana

Realmente muito estranho

Sabemos que a chamada de super() no primeiro construtor é inútil, mas no segundo faz sentido, mas parece que ele ignora esta chamada.

Mesmo sendo forçado ele continua com a mesma saida
assim:

public MyThread(Runnable runnable) { //super(runnable); super( new MyRunnable() ); System.out.println("construtor 2"); }

Na verdade, o que pude entender é que o java dá prioridade para uma herança sobre uma implementação.

Quando nós passamos uma classe que extende Runnable para Thread, esta classe sabe que nada há no método run da classe Thread, e por isso chama o método run da Runnable que foi passada.

Já quando há uma herança, ele ignora a classe Runnable passada, e executa o run da classe.

Teste o código seguinte:

public class MyThread extends Thread {

	public MyThread(){}

	public MyThread(Runnable runnable) {
		super(runnable);
	}
	
	public static void main(String... args) {

		//new MyThread().start();

		new MyThread(new MyRunnable()).start();

		new Thread(new MyRunnable()).start();
	}
}

class MyRunnable implements Runnable {
	public void run() {
		System.out.println("alou from MyRunnable");
	}
}

e terá duas saídas alou from MyRunnable

Criado 12 de novembro de 2006
Ultima resposta 22 de nov. de 2006
Respostas 7
Participantes 5