Хороший небольшой пример для демонстрации методов wait () и notify () в java - PullRequest
8 голосов
/ 02 декабря 2011

Может ли кто-нибудь предоставить мне хороший небольшой пример, демонстрирующий функциональность wait () и notify () в java. Я пробовал с приведенным ниже фрагментом кода, но он не показывает, что я ожидал.

public class WaitDemo {
    int i = 10;

    int display() {
        System.out.println("Lexmark");
        i++;
        return i;
    }
}
public class ClassDemo1 extends Thread {

    private WaitDemo wd = new WaitDemo();

    public static void main(String[] args) {
        ClassDemo1 cd1 = new ClassDemo1();
        ClassDemo1 cd2 = new ClassDemo1();
        cd1.setName("Europe");
        cd2.setName("America");
        cd1.start();
        cd2.start();

    }

    synchronized void display() {
        System.out.println("Hello");
        notifyAll();
    }

    public void run() {

        synchronized (this) {
            try {
                {
                    notify();
                    System.out.println("The thread is " + currentThread().getName());
                    wait();
                    System.out.println("The value is " + wd.display());
                }
            } catch (InterruptedException e) {

            }

        }
    }
}

Проблема в том, что метод в классе WaitDemo не выполняется, и, согласно моей идее, должна выполняться SOP после wait (). Пожалуйста, помогите мне в этом.

Ответы [ 7 ]

3 голосов
/ 23 октября 2015

Ниже приведен пример ожидания и уведомления в классе Object.Клиент пытается вывести деньги на сумму 2000, но на счету только 1000, поэтому он должен дождаться депозита.После внесения депозита клиент сможет вывести сумму.До внесения депозита клиент будет ждать.

class Cust {

    private int totalAmount = 1000;

    public synchronized void withdrawal(int amount) {
        System.out.println("Total amount " + totalAmount + " withdrawing amount " + amount);
        while (this.totalAmount < amount) {
            System.out.println("not enough amount..waiting for deposit..");
            try { wait(); } catch (Exception e) {}
        }
        this.totalAmount -= amount;     
        System.out.println("Withdrawal successful.. Remaining balance is "+totalAmount);    
    }

    public synchronized void deposit(int amount){
        System.out.println("Depositing amount "+amount);
        this.totalAmount += amount;
        System.out.println("deposit completed...and Now totalAmount is " + this.totalAmount);
        notify();
    }
}

class Depo implements Runnable {
    Cust c; int depo;

    Depo(Cust c, int depo){
        this.c = c;
        this.depo = depo;
    }

    @Override
    public void run() {
        c.deposit(depo);    
    }
}

class Withdrawal implements Runnable {
    Cust c; int with;

    Withdrawal(Cust c, int with){
        this.c = c;
        this.with = with; 
    }

    @Override
    public void run() {
        c.withdrawal(with);
    }
}

public class ObjectWaitExample {

    public static void main(String[] args) {
        Cust c = new Cust();
        Thread w = new Thread(new Withdrawal(c, 2000));
        Thread d1 = new Thread(new Depo(c, 50));
        Thread d2 = new Thread(new Depo(c, 150));
        Thread d3 = new Thread(new Depo(c, 900));
        w.start();
        d1.start();
        d2.start();
        d3.start();
    }

}
3 голосов
/ 02 декабря 2011

У вас есть два уровня скобок { в вашем блоке try.Если вы удалите внутренний набор (который, похоже, ничего не делает), это решит проблему?

Есть несколько примеров, каждый из которых демонстрирует использование.Последняя ссылка - это набор результатов, которые могут вам помочь.Если вам нужны более конкретные вещи, дайте мне знать, что именно пытается сделать ваше приложение, и я могу попытаться найти примеры, более специфичные для вашей ситуации.

1 голос
/ 22 марта 2016

Я создал два потока, один для печати нечетных чисел (OddThread) и другой для четных чисел (EvenThread). Внутри метода run каждого из потоков я использовал общий объект класса Print для вызова printOdd () и printEven () для Odd и EvenThread соответственно. Я сделал общий объект Print статическим, чтобы была сделана только одна копия. Теперь, синхронизируя объект Print, я использовал логический флаг, так что когда нечетный поток печатает нечетное число, он будет отправлен в состояние ожидания и в то же время уведомит четный поток о выполнении. Логика написана таким образом, что нечетный поток всегда сначала печатает нечетное число, несмотря ни на что, поскольку флаг изначально установлен в значение «ложь», предотвращая выполнение четного потока и отправляя его в состояние ожидания.

        package com.amardeep.test;

        public class ThreadDemo {
            // Shared object
            static Print print = new Print();

            public static void main(String[] args) {

                new Thread(new OddThread()).start();
                new Thread(new EvenThread()).start();

            }
        }

        class EvenThread implements Runnable {

            @Override
            public void run() {
                ThreadDemo.print.printEven();

            }

        }

        class OddThread implements Runnable {

            @Override
            public void run() {

                ThreadDemo.print.printOdd();
            }

        }

        class Print {
            public volatile boolean flag = false;

            public synchronized void printEven() {

                for (int i = 1; i <= 10; i++) {
                    if (!flag) {
                        try {
                            wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    } else {
                        if (i % 2 == 0) {
                            System.out.println("from even " + i);
                            flag = false;
                            notifyAll();
                        }

                    }
                }
            }

            public synchronized void printOdd() {
                for (int i = 1; i <= 10; i++) {
                    if (flag) {
                        try {
                            wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    } else {
                        if (i % 2 != 0) {
                            System.out.println("from odd " + i);
                            flag = true;
                            notifyAll();
                        }

                    }
                }
            }
        }
    output:-
    from odd 1
    from even 2
    from odd 3
    from even 4
    from odd 5
    from even 6
    from odd 7
    from even 8
    from odd 9
    from even 10
0 голосов
/ 05 ноября 2017

Что делает метод ожидания, когда некоторый поток выполнил синхронизированный блок, заблокировав некоторый объект (мы называем этот объект "a"), то внутри этого синхронизированного блока, когда поток выполнил метод ожидания объекта "a", как этот

A a = new A (); // some class object call "a"
  synchronized (a){
  a.wait ();//exceptions must be handled
}

Затем объект освобождается, и поток должен перейти в состояние ожидания, пока он не будет освобожден из этого состояния.

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

 a.notify ()

Затем один из потоков, перешедших в состояние ожидания с помощью объекта "a", может быть освобожден из состояния ожидания. В противном случае при вызове notifyAll все объекты потока выйдут из этого состояния.

0 голосов
/ 01 октября 2012
/*
 *  the below program is like 
 * tread t1 will first run , and it comes to "notify()" method
 * there are no threds waiting bcoz this is the first thread.
 * so it will not invoke any other threads. next step is "wait()" method
 *will be called and the thread t1 in waiting state. next stament 
 * "System.out.println("The value is ..."+wd.display());" will not be  executed
 * because thread t1 is in waiting state.
 * 
 * thread t2 will run ,and it comes to "notify()" method ,there is already 
 * thread t1 is in waiting state ,then it will be invoked.now thread t1 will
 * continue execution and it prints the statement "System.out.println("The value is ..."+wd.display())"
 * and thread t2 will be in waiting state now.
 * 
 * if you uncomment "notifyAll()" method then, after t1 thread completes its execution
 *then immediately "notifyAll()" method will be called,by that time thread t2 is 
 * already in waiting state , then thread t2 will be invoked and continues execution.
 *or
 * if any other threadds are in waiting state all those threads will be invoked.
 */
package threadsex;

/**
 *
 * @author MaheshM
 */
/**
 * @param args the command line arguments
 */
public class WaitNotifyNotifyAllDemo implements Runnable {
    WaitDemo wd = new WaitDemo();

    public static void main(String[] args) {
        WaitNotifyNotifyAllDemo cd1 = new WaitNotifyNotifyAllDemo();
        Thread t1 = new Thread(cd1);
        t1.setName("mahi1");
        Thread t2 = new Thread(cd1);
        t2.setName("mahi2");
        t1.start();         
        t2.start();
    }

    @Override
    public void run() {
        synchronized (this) {
            try {

                System.out.println("The thread is=" + 
                        Thread.currentThread().getName());
                notify();
                wait();
                System.out.println("The value is ..." + wd.display());
                //         notifyAll();

            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }
}
0 голосов
/ 02 декабря 2011

Я только что обновил этот ответ , чтобы включить SCCE .

Рабочие вызывают pauseIfNeeded в WorkerPauseManager. Если менеджер приостанавливается, когда рабочий поток вызывает pauseIfNeeded (), мы вызываем wait (), который сообщает вызывающему потоку ждать, пока другой поток не вызовет notify () или notifyAll () для ожидаемого объекта. Это происходит, когда поток диспетчера событий Swing вызывает play () для менеджера, который, в свою очередь, вызывает notifyAll ().

Обратите внимание, что у вас должна быть синхронизированная блокировка для объекта, для которого вы вызываете wait () или notify (). Поскольку методы в WorkerPauseManager синхронизированы, все синхронизированные методы получают синхронизированную блокировку на самом WorkerPauseManager.

import javax.swing.*;
import java.awt.event.ActionEvent;

/**
 * @author sbarnum
 */
public class WorkerPauseManagerTest {
    public static void main(String[] args) {
        final WorkerPauseManager pauseManager = new WorkerPauseManager();
        new Worker("Worker 1", pauseManager).start();
        new Worker("Worker 2", pauseManager).start();
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JToggleButton playPauseButton = new JToggleButton(new AbstractAction("Pause") {
                    public void actionPerformed(final ActionEvent e) {
                        JToggleButton source = (JToggleButton) e.getSource();
                        if (source.isSelected()) {
                            pauseManager.start();
                            source.setText("Pause");
                        } else {
                            pauseManager.pause();
                            source.setText("Play");
                        }
                    }
                });
                playPauseButton.setSelected(true); // already running
                JOptionPane.showMessageDialog(null, playPauseButton, "WorkerPauseManager Demo", JOptionPane.PLAIN_MESSAGE);
                System.exit(0);
            }
        });

    }

    private static class Worker extends Thread {
        final String name;
        final WorkerPauseManager pauseManager;

        public Worker(final String name, final WorkerPauseManager pauseManager) {
            this.name = name;
            this.pauseManager = pauseManager;
        }

        @Override
        public void run() {
            while (!Thread.interrupted()) {
                try {
                    pauseManager.pauseIfNeeded();
                    System.out.println(name + " is running");
                    Thread.sleep(1000L);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    public static final class WorkerPauseManager {

        private boolean paused;

        public synchronized void pauseIfNeeded() throws InterruptedException {
            if (paused) wait();
        }

        public synchronized void pause() {
            this.paused = true;
        }

        public synchronized void start() {
            this.paused = false;
            notifyAll();
        }
    }
}
0 голосов
/ 02 декабря 2011

Ваша проблема в том, что вы создаете два экземпляра класса Thread. Таким образом, когда вызывается wait (), это происходит в двух разных экземплярах, ни в одном из которых нет другого потока, который находится в конфликте за ваш монитор, и нет другого потока, который вызывает notifyAll (), чтобы вывести поток из состояния ожидания.

Таким образом, каждый запущенный вами поток будет ждать вечно (или пока не прервется по какой-либо другой причине).

Вы хотите, чтобы несколько потоков обращались к одному и тому же монитору, поэтому начните с попытки закодировать что-то, в чем рассматриваемый код на самом деле не является потоком, а просто используется потоком.

@ normalocity уже предоставил ссылки на несколько примеров.

...