Поиск по сайту:

Java Thread ждет, уведомляет и уведомляет пример All


Класс Object в Java содержит три последних метода, которые позволяют потокам сообщать о состоянии блокировки ресурса. Это методы wait(), notify() и notifyAll(). Итак, сегодня мы рассмотрим ожидание, уведомление и уведомление всех в java-программе.

ждать, уведомлять и уведомлять всех в Java

ждать

Методы ожидания объекта имеют три варианта, один из которых бесконечно ожидает, пока любой другой поток не вызовет метод notify или notifyAll для объекта, чтобы разбудить текущий поток. Другие две вариации помещают текущий поток в ожидание на определенное время, прежде чем он проснется.

поставить в известность

метод notify пробуждает только один поток, ожидающий объекта, и этот поток начинает выполнение. Поэтому, если есть несколько потоков, ожидающих объекта, этот метод разбудит только один из них. Выбор потока для пробуждения зависит от реализации управления потоками в ОС.

уведомить всех

Метод notifyAll пробуждает все потоки, ожидающие объекта, хотя какой из них будет обрабатываться первым, зависит от реализации ОС. Эти методы можно использовать для реализации проблемы производителя-потребителя, когда потоки-потребители ожидают объекты в очереди, а потоки-производители помещают объект в очередь и уведомляют ожидающие потоки. Давайте рассмотрим пример, в котором несколько потоков работают с одним и тем же объектом, и мы используем методы ожидания, уведомления и уведомления.

Сообщение

Класс Java-бина, в котором будут работать потоки и вызывать методы ожидания и уведомления.

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;
    }

}

Официант

Класс, который будет ждать, пока другие потоки вызовут методы уведомления, чтобы завершить его обработку. Обратите внимание, что поток ожидания владеет монитором объекта Message, используя синхронизированный блок.

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());
        }
    }

}

Уведомитель

Класс, который будет обрабатывать объект Message, а затем вызывать метод уведомления для пробуждения потоков, ожидающих объект Message. Обратите внимание, что блок synchronized используется для владения монитором объекта 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();
        }
        
    }

}

ПодождитеNotifyTest

Тестовый класс, который создаст несколько потоков Waiter и Notifier и запустит их.

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");
    }

}

Когда мы вызовем вышеуказанную программу, мы увидим вывод ниже, но программа не будет завершена, потому что есть два потока, ожидающих объекта Message, и метод notify() разбудил только один из них, а другой поток все еще ожидает получения уведомления.

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

Если мы прокомментируем вызов notify() и раскомментируем вызов notifyAll() в классе Notifier, ниже будет получен результат.

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

Поскольку метод notifyAll() пробуждает как потоки ожидания, так и программа завершается и завершается после выполнения. Это все для ожидания, уведомления и уведомления All в java.