Mais uma(s) dúvida(s) de Thread

3 respostas
G

O exercício é o seguinte:
[color=blue]
Dado o método run de uma Thread, qual (sic, esse livro Certificação Java 5 do Serson tem muuitos erros… os de concordância são os menos importantes :roll: ) são os modos na qual a Thread certamente sairá do estado de espera?
[/color]

public void run() { synchronized (this){ try { wait(5000); } catch(InterruptException ie) {} } }
[color=blue]
Selecione múltiplas opções:
A) Outra Thread na qual pertence o bloqueio do objeto invoca o método notify()
B) Outra Thread na qual pertence o bloqueio do objeto invoca o método notifyAll()
C) O período de 5000 milissegundos já transcorreu
D) Outra Thread invoca o join() na Thread
E) Outra Thread invoca o interrupted() na Thread
F) Outra Thread invoca o resume() na Thread
[/list][/color]

Achei que a única correta seria a C, porém na resposta do livro está como
B, C e E.
A “C” tudo bem… minhas dúvidas são:

Na alternativa “B”, quando a Thread no código acima dá um “synchronized (this)”, ela não está locando a própria Thread? O que quer dizer “Outra Thread na qual pertence o bloqueio do objeto”? Qual objeto?

Na “E”… no javadoc diz “The interrupted status of the thread is cleared by this method”, isso quer dizer que a Thread sai do wait?
interrupted() é static… todas as instâncias dessa Thread saem de wait?

Desculpem-me pelo tamanho da pergunta e quantidade de dúvidas!!!
Tks

3 Respostas

ViniGodoy

Uma grande dúvida, exige um resposta grande...

B) Outra thread na qual percente o bloqueio do objeto invoca o método notify all;
Quando você chama o wait(), abre mão do objeto (chamador de monitor), e outras threads poderão entrar no código sincronizado.

Se uma thread percorrer um outro bloco, que contém como chave de sincronização o mesmo monitor, e chamar notify() ou notifyAll(), sua thread poderá sair do wait, e reobter o monitor para prosseguir a execução no bloco sincronizado.

Esse comportamento é descrito no próprio javadoc do método wait:
"This method causes the current thread (call it T) to place itself in the wait set for this object and then to relinquish any and all synchronization claims on this object. (...)"

Lembre-se a assinatura do synchronized é:
synchronized (<objeto monitor>) {
   //Código sincronizado
}

Por exemplo na classe abaixo:

public class Sleeper() {
   boolean isSleeping = false;
   public void delay(int millis) {
      if (millis &lt= 0) return;
      synchronized (this) { //This é o monitor
         isSleeping = true;
         try {
            while (isSleeping)
               wait(millis); 
         } catch (InterruptedException e) {}
      }
   }

   public void wakeUp() {
      synchronized (this) {
         isSleeping = false;
         notifyAll();
      }
   }
}

Uma thread (A) poderia chamar o método sleep e seria posta para dormir. Isso liberaria o monitor this. Outra thread (B), então, chama o método wakeUp(). B consegue entrar no corpo do bloco sincronizado, pois o this não pertence mais a thread A. B troca o valor de isSleeping e então chama notifyAll e, assim que sair do bloco sincronizado, a thread A irá acordar e continuar sua execução. Veja ainda este exemplo com um programa com esse mecanismo funcionando.

E) Outra Thread invoca o interrupt() na Thread
Quando outra thread invoca o método interrupt, todos os waits são abandonados e lançam uma interrupted exception. Embora o interrupt possa ser usado como um mecanismo de parada para a thread, isso não é muito recomendado. Considere o uso de interrupt para o uso da VM, quando a aplicação estiver sendo finalizada. Veja este exemplo, onde um grupo de threads é parado chamando interrupt.

Note que, se você tivesse colocado o try..catch do InterruptedException dentro do while, a thread não seria interrompida. Via de regra, não faça isso. Considere que o interrupt é lançado ao final da sua aplicação, saia do while e rode algum código de finalização (fechamento de arquivo, sockets ou outros recursos que seu objeto possam estar em uso).

Existem ainda uma outras situações, que não foram descritas por essa questão, e geralmente geram dúvida:

G) O wait termina antes do prazo, sem motivo aparente algum.
É verdade. Esse comportamento é chamado de spurious wakeup e você pode até mesmo encontrar a descrição dele no javadoc do método wait(). Isso normalmente não é problema, pois o wait é precedido de uma condição, que o mantém num while (como na classe acima, a condição é isSleeping). Mas pode dar um pouco de trabalho caso o seu sistema exija que o timeout do wait seja rigorosamente cumprido.

H) Outra thread invoca o stop() na thread
Em primeiríssimo lugar, é importante lembrar que o stop é um método deprecated. Quando você pega o objeto que descreve a thread e chama stop nele, a thread é imediatamente interrompida. Não interessa se ela está ou não bloqueada. Nenhum código de finalização é chamado. Via de regra, não use esse recurso. Pode clicar aqui para uma descrição mais detalhada do porquê.

G

Cara, mil desculpas mas acabei saido do ar e parei com os estudos… retomei agora, muitissimo obrigado pela resposta rápida e completa!

LPJava

ViniGodoy arrebenta com Threads nunca vi heheh parabens!! as respostas dele sempre sao simples, claras e eficientes… muito bom mesmo :smiley:

Criado 21 de abril de 2007
Ultima resposta 24 de mai. de 2007
Respostas 3
Participantes 3