Acho que é porque o contexto da sincronização na main Thread está no objeto b. Logo, o notifyAll irá propagar apenas para a Thread b, pos a Thread c está sincronizando para si mesmo.
rodrigo.bossini
Exatamente. O Notify (ou notifyAll, como neste caso) “notifica” somente a(s) thread(s) que estiverem aguardando no objeto em que você chama o notify (ou notifyAll).
A Thread C ficará aguardando eternamente, já que você nunca chama notify no objeto que representa a thread C, que por acaso é o objeto em que ela espera.
jjose
Entendi, nesse caso , basta eu colocar um notify para C tambem.
O que eu queria é ver o notifyAll propagando a liberação de mais thread, alguem sabe como fazer isso no exemplo?
rodrigo.bossini
Você pode, por exemplo, criar um objeto no metodo main, e passar ele para ambas as threads, B e C, via construtor, e fazê-lar dar wait neste objeto. Assim no main, você dá um notifyAll neste objeto e ambas as threads B e C serão afetadas. Só tome cuidado que seu código é arriscado: Main pode invocar notifyALL antes que uma das threads B ou C, ou até mesmo as duas tenham invocado wait. Neste caso as duas ficaram aguardando para sempre.
jjose
O que eu entendi é o código em baixo e não funciona, trava geral. Seu eu coloco wait no contrutor da ThreadA a thread principal fica esperando eternamento.
Eu não entendi mesmo. Podem me ajudar via codigo para eu entender? Sem while, for… coisa simples mesmo
Acho que você não entendeu o que o amigo quis dizer. As três Threads precisam ter um objeto em comum. As Thread b e c não fazem ideia de que a Thread a existe.
Olhe abaixo:
classReaderextendsThread{Calculatorc;publicReader(Calculatorcalc){c=calc;}publicvoidrun(){synchronized(c){try{System.out.println("Waiting for calculation...");c.wait();}catch(InterruptedExceptione){}System.out.println("Total is: "+c.total);}}publicstaticvoidmain(String[]args){Calculatorcalculator=newCalculator();newReader(calculator).start();newReader(calculator).start();newReader(calculator).start();calculator.start();}}classCalculatorextendsThread{inttotal;publicvoidrun(){synchronized(this){for(inti=0;i<100;i++){total+=i;}notifyAll();}}}
Olhe esse exemplo que tirei do livro da Kathy. Os objetos Reader tem um objeto Calculator em comum. Esse é o elo de ligação entre o notify.
jjose
yastorm:
Acho que você não entendeu o que o amigo quis dizer. As três Threads precisam ter um objeto em comum. As Thread b e c não fazem ideia de que a Thread a existe.
Olhe abaixo:
public void run() {
synchronized (this) {
for (int i = 0; i < 100; i++) {
total += i;
}
//notifyAll();
}
}
}
Olhe esse exemplo que tirei do livro da Kathy. Os objetos Reader tem um objeto Calculator em comum. Esse é o elo de ligação entre o notify.
Eu tinha visto esse exemplo e o que pegou dele é, com ou sem o notifyAll o resultado é o mesmo.
Estou boiando nesse notifyAll :shock:
jjose
Ninguem? Hehehe
E
entanglement
Rode o programa abaixo e veja por que talvez você esteja tendo problemas.
De modo geral, wait + notify é a mesma coisa que goto para threads; é uma forma muito básica e muito difícil de usar. Se precisar de sincronização entre threads, use alguma classe de java.util.concurrent.
packageguj;classThread1implementsRunnable{publicThread1(Objectlock){this.lock=lock;}@Overridepublicvoidrun(){System.out.println("Thread 1 está esperando...");synchronized(lock){try{lock.wait();}catch(InterruptedExceptione){e.printStackTrace();}}System.out.println("Thread 1 foi acordada");}privateObjectlock;}classThread2implementsRunnable{publicThread2(Objectlock){this.lock=lock;}@Overridepublicvoidrun(){System.out.println("Thread 2 está esperando...");synchronized(lock){try{lock.wait();}catch(InterruptedExceptione){e.printStackTrace();}}System.out.println("Thread 2 foi acordada");}privateObjectlock;}classThread3implementsRunnable{publicThread3(Objectlock){this.lock=lock;}@Overridepublicvoidrun(){System.out.println("Thread 3 está esperando...");synchronized(lock){try{lock.wait();}catch(InterruptedExceptione){e.printStackTrace();}}System.out.println("Thread 3 foi acordada");}privateObjectlock;}publicclassTesteNotifyAll{publicstaticvoidmain(String[]args){Objectlock=newObject();Threadthr1=newThread(newThread1(lock));Threadthr2=newThread(newThread2(lock));Threadthr3=newThread(newThread3(lock));thr1.start();thr2.start();thr3.start();// Note que aqui estou dando tempo suficiente para todas as threads iniciarem.// Você não pode acordar uma thread (que está em wait) se ela ainda não chegou // no wait! Pode ser isso que deu problema no seu programa. // E é por isso que é extremamente difícil trabalhar com threads usando só wait e// notify. Prefira usar as classes de java.util.concurrent.try{Thread.sleep(2000);}catch(InterruptedExceptionex){}System.out.println("Acordando uma ou mais threads");synchronized(lock){lock.notifyAll();}try{thr1.join();}catch(InterruptedExceptionex){}try{thr2.join();}catch(InterruptedExceptionex){}try{thr3.join();}catch(InterruptedExceptionex){}}}