Pesquisa de site

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.

Artigos relacionados: