Thread dúvida questão 9 Kathy Sierra

Given:

public static synchronized void main( String[] args ) throws InterruptedException {
   Thread t = new Thread();
   t.start();
   System.out.print( "X" );
   t.wait( 10000 );
   System.out.print( "Y" );
}

What is the result of this code?
A. It print X and exits
B. It print Y and never exits
C. It print XY and exits almost immeditately
D. It print XY width 10-second delay between X and Y
E. It print XY width 10000-second delay between X and Y
F. The code does not compile
G. An exception is thrown at runtime

resposta…: G
Alguém pode me responder por que?

Desde já agradeço

ACHO… que é por que a Thread t não foi definida como um monitor.

Antes de explicar esse problema, vamos diferenciar algumas coisas:

a) O método wait() é um método de um objeto, não de uma thread. Ele faz com que a thread atual pare, até que outra thread chame o método notify() sobre o mesmo objeto.
b) Para toda thread criada em Runtime, teremos a thread em si (a linha de execução) e um objeto, que representa essa thread, e é filho da classe Thread. Note que a thread e o objeto que a representa são coisas diferentes.
c) Para que os métodos wait() e notify() possam ser chamados, o objeto tem que ser o monitor. Você faz isso colocando ele como parâmetro de um bloco synchronized.

Pois bem, nesse exemplo, criamos um objeto do tipo Thread, e o chamamos de t. Depois, usamos ele para disparar outra thread. A outra thread não tem qualquer relevância para a analise do problema. Ela provavelmente vai iniciar e morrer logo em seguida, já que nem runnable tem.

O que interessa mesmo é o que acontece na main thread. Ela tem um método main sincronizado. Isso significa que o monitor está na ClassDoMain.class e não no objeto t. E é no objeto t que o wait está sendo chamado. Quando o método wait() for invocado a exceção de que o objeto t não é um monitor será lançada.

A correção para esse código ficaria:
Given:

public static void main( String[] args ) throws InterruptedException { Thread t = new Thread(); t.start(); System.out.print( "X" ); synchronized (t) { t.wait( 10000 ); } System.out.print( "Y" ); }

Note que t poderia pertencer a qualquer outra classe, como String. Pouco importa dele ser um objeto que descreve uma thread ou não.

Estava meio dormindo quando escrevi ali em cima. E agora melhorei a explicação. Esse horário depois do almoço é mesmo complicado.

mas o métdo main não é synchronize? como t.wait() vai gerar um exceção se esta num ambiente sincronizado?

Um abração

Toda sincronização elege como monitor um objeto. E é nesse objeto que precisamos chamar o método wait.
Em outros objetos, o comando irá lançar a exceção, indicando que o objeto não é o monitor.

Por exemplo, abaixo um código que usa “lock” como monitor:

[code]
public class Classe {
private int[0] lock = new int[0]; //Um objeto qualquer

public void metodo() {
synchronized (lock) { //lock é o monitor
lock.wait(1000);
}
}
}[/code]

O que acontece quando declaramos um método como synchronized?
Se o método não for estático, o objeto do lock é o this. Portanto, os dois métodos abaixo tem sincronização equivalente:

public class Classe { public void metodo1() { synchronized (this) { // wait(1000); } } public synchronized void metodo2() { wait(1000); } }

Logo, ambos os métodos são mutuamente excludentes.

E se o método for static? Nesse caso, a sincronização acontecerá sobre o class:

public class Classe { public static void metodo1() { synchronized (Classe.class) { // wait(1000); } } public synchronized static void metodo2() { wait(1000); } }

No código que você passou, a sincronização do método main está ocorrendo num class. É nesse objeto de lock que a main thread está. Entretanto, ele está tentando chamar o wait do objeto t. Veja, aquele wait não tem qualquer efeito sobre a thread que o objeto t criou, ele atua sobre a main thread.

Vamos reescrever aquele código numa versão equivalente, usando a sintaxe do monitor explícito:

public class Classe { public static void main( String[] args ) throws InterruptedException { synchronized (Classe.class) { //O monitor é classe.class Thread t = new Thread(); t.start(); System.out.print( "X" ); t.wait( 10000 ); //Ops! Estamos chamando wait em t, não em Classe.class! System.out.print( "Y" ); } } }

E lembrando que wait/notify foi retirado da SCJP na ultima revisão, em agosto.

putz…serio? posso ti pedir essas revisões? para saber o que mais foi retirado.

a descrição nova está aqui: http://www.sun.com/training/catalog/courses/CX-310-065.xml

saíram: wait/notify, serialização, java beans, varargs, e algumas APIs de java.io

[quote=Sergio Lopes]a descrição nova está aqui: http://www.sun.com/training/catalog/courses/CX-310-065.xml

saíram: wait/notify, serialização, java beans, varargs, e algumas APIs de java.io[/quote]

Nosso, então esta bem mais fácil, mais pena que pelo SAI ainda esta no modelo antigo.

[quote=taaqui][quote=Sergio Lopes]a descrição nova está aqui: http://www.sun.com/training/catalog/courses/CX-310-065.xml

saíram: wait/notify, serialização, java beans, varargs, e algumas APIs de java.io[/quote]

Nosso, então esta bem mais fácil, mais pena que pelo SAI ainda esta no modelo antigo.[/quote]

pois é, eu confirmo :evil:

eu fui fazer a prova sem saber disso, e na semana anterior eu praticamente me matei de ver thread, serialização, varags e IO. A unica coisa que eu tinha deichado de lado era o java beans … quase me fo** :x