Olá pessoal do GUJ
Li alguns tópicos sobre Interação aqui mas não achei uma resposta para a minha pergunta! Bem ai Vai!
Tenho o Seguinte Código(como podem ver eu estava brincando com ele um Pouco):
public class Duvidas {
public static void main(String args[]) {
Other o = new Other();
o.setName("-A-");
Other oo = new Other();
oo.setName("-AA-");
o.start();
oo.start();
synchronized(o){
try{
System.out.println("waiting for O ...");
o.wait();
System.out.println("O is OK ...");
}catch(InterruptedException e){
System.out.println("Total: " + o.total);
}
}
synchronized(oo){
try{
System.out.println("waiting for OO ...");
oo.wait();
System.out.println("OO is OK ...");
}catch(InterruptedException e){
System.out.println("Total: " + oo.total);
}
}
}
}
class Other extends Thread{
int total;
public void run(){
synchronized(this){
System.out.println("Inicio" +Other.currentThread().getName());
for(int i = 0; i < 10 ; i++){
try {
sleep(400);
System.out.println("Run: "+i+" "+Other.currentThread().getName());
total += i;
}catch (InterruptedException ex) {
System.out.println(ex);
}
}
notifyAll();
}
}
}
Com a Saida(Não Garantida é Claro):
run:
waiting for O … //Ok! entrei no Bloco Synchronyzed
Inicio-A- //OK! Entrei em run() com a Thread "o"
Inicio-AA- //OPA! Como assim? run() Sem Entrar no Bloco Synchronyzed de "oo"
Run: 0 -A-
Run: 0 -AA-
Run: 1 -AA-
Run: 1 -A-
Run: 2 -AA-
Run: 2 -A-
Run: 3 -AA-
Run: 3 -A-
Run: 4 -AA-
Run: 4 -A-
Run: 5 -AA-
Run: 5 -A-
Run: 6 -AA-
Run: 6 -A-
Run: 7 -AA-
Run: 7 -A-
Run: 8 -AA-
Run: 8 -A-
Run: 9 -AA-
Run: 9 -A-
O is OK …
waiting for OO … // Agora que ele vai querer aguardar! e o programa nunca termina!
Bem eu sei que pra poder ter a garantia(que não é verdade pois o agendador é imprevisível) de uma saida uniforme eu preciso sincronizar a classe (Ex: synchronized(Other.class) ), mas não entendo por que quando a 2ª thread “Starta” ela só procura o bloco sincronizado quando termina de rodar(run())?
para deixar mais claro gostaria de saber por que não tenho uma saida mais ou menos assim:
run:
waiting for O … // Entra no Bloco Sincronizado depois em run() …
waiting for OO … // Deixa da rebeldia e também entra no bloco sincronizado antes de entrar em run().
Inicio-A-
Inicio-AA-
Run: 0 -A-
Run: 0 -AA-
Run: 1 -AA-
Run: 1 -A-
Run: 2 -AA-
Run: 2 -A-
Run: 3 -AA-
Run: 3 -A-
Run: 4 -AA-
Run: 4 -A-
Run: 5 -AA-
Run: 5 -A-
Run: 6 -AA-
Run: 6 -A-
Run: 7 -AA-
Run: 7 -A-
Run: 8 -AA-
Run: 8 -A-
Run: 9 -AA-
Run: 9 -A-
O is OK …
OO is OK …
Resumo do resumo
Por que a 2ª thread não faz como a primeira (o -> sync() -> run()) e pula logo pra segunda(oo -| sync() -> run())
Não sei se fui claro, mas caso não avisa ai que eu tento explicar de maneira mais detalhada.
Dependendo da ordem que as operações forem executadas, o método notifyAll pode ser executado antes do wait, por isso que o programa trava, pois ele irá esperar um notifyAll que nunca ocorrerá (já que ele já ocorreu em um momento anterior). Pra testar isso, eu modifiquei o código da seguinte forma:
package teste.concorrencia;
public class Duvidas {
public static void main(String args[]) throws InterruptedException {
Other o = new Other();
o.setName("-A-");
Other oo = new Other();
oo.setName("-AA-");
o.start();
oo.start();
synchronized(o){
try{
System.out.println("waiting for O ... Já executou o notifyAll? " + o.isJaExecuteiONotify());
o.wait();
System.out.println("O is OK ...");
}catch(InterruptedException e){
System.out.println("Total: " + o.total);
}
}
synchronized(oo){
try{
System.out.println("waiting for OO ... Já executou o notifyAll? " + oo.isJaExecuteiONotify());
oo.wait();
System.out.println("OO is OK ...");
}catch(InterruptedException e){
System.out.println("Total: " + oo.total);
}
}
}
}
class Other extends Thread{
int total;
private volatile boolean jaExecuteiONotify;
public boolean isJaExecuteiONotify() {
return jaExecuteiONotify;
}
public void run(){
synchronized(this){
System.out.println("Inicio" +Other.currentThread().getName());
for(int i = 0; i < 10 ; i++){
try {
sleep(400);
System.out.println("Run: "+i+" "+Other.currentThread().getName());
total += i;
}catch (InterruptedException ex) {
System.out.println(ex);
}
}
notifyAll();
jaExecuteiONotify = true;
}
}
}
Executa esse código novo e verá que na linha em que o código trava será exibido que a thread já executou o notifyAll antes do wait…
Se o seu objetivo é aguardar a execução das threads o melhor é utilizar o método join:
package teste.concorrencia;
public class Duvidas {
public static void main(String args[]) throws InterruptedException {
Other o = new Other();
o.setName("-A-");
Other oo = new Other();
oo.setName("-AA-");
o.start();
oo.start();
/*
synchronized(o){
try{
System.out.println("waiting for O ... Já executou o notifyAll? " + o.isJaExecuteiONotify());
o.wait();
System.out.println("O is OK ...");
}catch(InterruptedException e){
System.out.println("Total: " + o.total);
}
}
synchronized(oo){
try{
System.out.println("waiting for OO ... Já executou o notifyAll? " + oo.isJaExecuteiONotify());
oo.wait();
System.out.println("OO is OK ...");
}catch(InterruptedException e){
System.out.println("Total: " + oo.total);
}
}*/
o.join();
System.out.println("O is OK ...");
oo.join();
System.out.println("OO is OK ...");
}
}
class Other extends Thread{
int total;
private volatile boolean jaExecuteiONotify;
public boolean isJaExecuteiONotify() {
return jaExecuteiONotify;
}
public void run(){
synchronized(this){
System.out.println("Inicio" +Other.currentThread().getName());
for(int i = 0; i < 10 ; i++){
try {
sleep(400);
System.out.println("Run: "+i+" "+Other.currentThread().getName());
total += i;
}catch (InterruptedException ex) {
System.out.println(ex);
}
}
notifyAll();
jaExecuteiONotify = true;
}
}
}
Pow Obrigado, já havia percebido, mas gostaria de saber por que as duas threads não entram no primeiro Bloco Sincronizado(Somente a 1ª thread entra nos dois a segunda não)
Já percebeu que os métodos wait(), notify() e notifyAll() são métodos da classe Object, e não da classe Thread ?[/quote]
Hum … tava olhando o Código do Amigo rogeriopaguilar usando Wait() e sei que tem o comportamento que eu espero que tenha(por falar nisso belo código!) … Sabia sim que esses métodos são da CLasse Object, e que eu não tinha ligado o Nome a Pessoa … Então só tem esse comportamento devido isso? por serem da classe Object? eu ainda estou meio que me enrolando com Bloqueio e desbloqueio … com a ajuda de vocês eu estou quase entendendo mas ainda está meio nebuloso … Obrigado pela Atenção!
Já percebeu que os métodos wait(), notify() e notifyAll() são métodos da classe Object, e não da classe Thread ?[/quote]
Hum … tava olhando o Código do Amigo rogeriopaguilar usando Wait() e sei que tem o comportamento que eu espero que tenha(por falar nisso belo código!) … Sabia sim que esses métodos são da CLasse Object, e que eu não tinha ligado o Nome a Pessoa … Então só tem esse comportamento devido isso? por serem da classe Object? eu ainda estou meio que me enrolando com Bloqueio e desbloqueio … com a ajuda de vocês eu estou quase entendendo mas ainda está meio nebuloso … Obrigado pela Atenção![/quote]
É que a impressão que eu tive, é que talvez você esteja confundindo as coisas. Bom, se o método wait() pertence à classe Object, concorda comigo que ele pode ser chamado a partir de qualquer objeto, e não apenas de Threads correto ?
Pois bem, ocorre que chamando o método wait() você bloqueia a thread corrente, e não o objeto. No seu caso, quando você chama o.wait() ou oo.wait() você bloqueia a thread principal, e não as threads o e oo. Provavelmente acontece que a thread oo termina antes da thread principal chamar wait() e é encerrada, de forma que não sobra ninguém para chamar notifyAll() e destravar a thread principal.
Hum … Agora Sim as Coisas fazem sentido!!! OK era exatamente isso que eu queria entender … Valeuzão a todo pessoal do GUJ em especial ao companheiro rogeriopaguilar, que me deu a resposta, mas eu não consegui enxergar por não conhecimento e o companheiro rmendes08 que teve paciência de me ajudar a enxergar com mais clareza o que tava na minha cara hahahahaha … estou a 1 semana da prova e tenho tido bons resultados (Para quem saiu da inércia total) mas ainda apanho um pouco para Threads, continuarei com os estudos … Bem … Mais uma vez Obrigado e até um Próxima!
Olá conforme vc falou : [quote]
Pois bem, ocorre que chamando o método wait() você bloqueia a thread corrente, e não o objeto. No seu caso, quando você chama o.wait() ou oo.wait() você bloqueia a thread principal, e não as threads o e oo. Provavelmente acontece que a thread oo termina antes da thread principal chamar wait() e é encerrada, de forma que não sobra ninguém para chamar notifyAll() e destravar a thread principal. [/quote]
ola so queria q esclarecessem uma duvida que eu fiquei o primeiro bloco synchronized (o) bloqueia a thread “o” que fica esperando um notify .
(duvida)qual thread ela bloqueia a main ou a thread “o”?
Aqui em ksa nao houve bloqueio das threads durante a execução do run() só depois delas terem terminado, e portanto o código não avança nem para o segundo synchronized (oo) e a última mensagem é waiting for o… (ficou no primeiro synchronized a thread main) que provavelmente está (estão ) morta(as), então o synchronized dentro do run() nao funcionou muito pois ele teria que bloquear a thread até ela terminar… ou ele não garante isso ?
ok, acho q já entendi segundo a penúltima explicação postada nesse tópico . Então como fazer esse código (se é que é possível ) funcionar com wait() e notify() ? Mantendo as duas threads , só que uma avisa a outra que já acabou através do notify … :PPPP acho nem sei o q tou falando … queria saber primeiro o objeto desta classe Duvida , será que é o mesmo objetivo que eu estou pensando (o de funcionar duas threads concorrentemente através do notify)? ou tás brincando de deadlock??