Java Thread espera, notifica e notificaTodos os exemplos
A classe Object em java contém três métodos finais que permitem que os threads se comuniquem sobre o status de bloqueio de um recurso. Esses métodos são wait(), notify() e notifyAll(). Então, hoje vamos olhar para esperar, notificar e notificarAll no programa java.
aguarde, notifique e notifiqueTudo em Java
espere
Os métodos de espera do objeto têm três variações, uma que espera indefinidamente que qualquer outro encadeamento chame o método notify ou notifyAll no objeto para ativar o encadeamento atual. Outras duas variações colocam o thread atual em espera por um período de tempo específico antes de serem ativados.
notificar
O método notify ativa apenas um thread aguardando o objeto e esse thread inicia a execução. Portanto, se houver vários threads esperando por um objeto, esse método ativará apenas um deles. A escolha do encadeamento a ser ativado depende da implementação do sistema operacional de gerenciamento de encadeamento.
notificarTodos
O método notifyAll ativa todos os threads que estão esperando no objeto, embora qual deles será processado primeiro depende da implementação do sistema operacional. Esses métodos podem ser usados para implementar o problema do consumidor produtor em que as threads consumidoras estão esperando pelos objetos na fila e as threads produtoras colocam o objeto na fila e notificam as threads em espera. Vamos ver um exemplo onde vários threads trabalham no mesmo objeto e usamos os métodos wait, notify e notifyAll.
Mensagem
Uma classe de bean java na qual os encadeamentos funcionarão e chamarão os métodos de espera e notificação.
package com.journaldev.concurrency;
public class Message {
private String msg;
public Message(String str){
this.msg=str;
}
public String getMsg() {
return msg;
}
public void setMsg(String str) {
this.msg=str;
}
}
Garçom
Uma classe que aguardará que outras threads invoquem métodos de notificação para concluir seu processamento. Observe que o thread Waiter está controlando o monitor no objeto Message usando o bloco sincronizado.
package com.journaldev.concurrency;
public class Waiter implements Runnable{
private Message msg;
public Waiter(Message m){
this.msg=m;
}
@Override
public void run() {
String name = Thread.currentThread().getName();
synchronized (msg) {
try{
System.out.println(name+" waiting to get notified at time:"+System.currentTimeMillis());
msg.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(name+" waiter thread got notified at time:"+System.currentTimeMillis());
//process the message now
System.out.println(name+" processed: "+msg.getMsg());
}
}
}
Notificador
Uma classe que processará o objeto Message e, em seguida, invocará o método de notificação para ativar os threads que aguardam o objeto Message. Observe que o bloco sincronizado é usado para controlar o monitor do objeto Message.
package com.journaldev.concurrency;
public class Notifier implements Runnable {
private Message msg;
public Notifier(Message msg) {
this.msg = msg;
}
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.println(name+" started");
try {
Thread.sleep(1000);
synchronized (msg) {
msg.setMsg(name+" Notifier work done");
msg.notify();
// msg.notifyAll();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
WaitNotifyTest
Classe de teste que criará vários threads de Waiter e Notifier e os iniciará.
package com.journaldev.concurrency;
public class WaitNotifyTest {
public static void main(String[] args) {
Message msg = new Message("process it");
Waiter waiter = new Waiter(msg);
new Thread(waiter,"waiter").start();
Waiter waiter1 = new Waiter(msg);
new Thread(waiter1, "waiter1").start();
Notifier notifier = new Notifier(msg);
new Thread(notifier, "notifier").start();
System.out.println("All the threads are started");
}
}
Quando invocarmos o programa acima, veremos a saída abaixo, mas o programa não será concluído porque há dois threads esperando no objeto Message e o método notify() ativou apenas um deles, o outro thread ainda está esperando para ser notificado.
waiter waiting to get notified at time:1356318734009
waiter1 waiting to get notified at time:1356318734010
All the threads are started
notifier started
waiter waiter thread got notified at time:1356318735011
waiter processed: notifier Notifier work done
Se comentarmos a chamada notify() e descomentarmos a chamada notifyAll() na classe Notifier, abaixo estará a saída produzida.
waiter waiting to get notified at time:1356318917118
waiter1 waiting to get notified at time:1356318917118
All the threads are started
notifier started
waiter1 waiter thread got notified at time:1356318918120
waiter1 processed: notifier Notifier work done
waiter waiter thread got notified at time:1356318918120
waiter processed: notifier Notifier work done
Como o método notifyAll() ativa os threads Waiter e o programa é concluído e encerrado após a execução. Isso é tudo para esperar, notificar e notificarTudo em java.