【问题标题】:A good small example to demonstrate wait() and notify() method in java一个很好的小例子来演示 java 中的 wait() 和 notify() 方法
【发布时间】:2011-12-02 15:27:25
【问题描述】:

谁能给我一个很好的小例子来演示java中的wait()和notify()功能。我已经尝试使用下面的代码,但它没有显示我的预期。

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 类中的方法没有被执行,按照我的想法,wait() 之后的 SOP 应该执行。请帮我解决这个问题。

【问题讨论】:

  • 这不就是谷歌的目的吗?
  • @Крысa:请记住,SO 的目标之一是成为 Google(和其他)搜索的热门搜索。这是一个完全合理的问题。应该用一个例子来回答——这里是关于 SO,而不是其他地方——并讨论(理想情况下)Sourav 在上面哪里出错了。
  • 这个程序的预期行为是什么?
  • Sourav,为了帮助人们帮助你,请获得一个好的代码格式化程序来处理... 不寻常 ...代码缩进样式。我不是要发起一场风格大战,但你必须接受上述不是通常的事情,保持通常的事情会帮助人们帮助你。恕我直言,它看起来真的很草率且难以理解,根本不像真正的风格...... 更新:啊,@Alex K 为你修好了。

标签: java multithreading wait notify


【解决方案1】:

您的try 块中有两个级别的大括号​​{。如果您删除内部集合(它似乎没有做任何事情),这是否解决了问题?

周围有几个示例,所有示例都演示了使用方法。最后一个链接是一组可以帮助您的结果。如果您需要更具体的内容,请告诉我您的应用正在尝试做什么,我可以尝试找到更适合您情况的示例。

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 我已将if 更改为while 以防止出现负余额。
    【解决方案3】:

    我创建了两个线程,一个用于打印奇数 (OddThread),另一个用于打印偶数 (EvenThread)。在每个线程的 run 方法中,我使用类 Print 的共享对象分别为 Odd 和 EvenThread 调用 printOdd() 和 printEven()。我将 Print 的共享对象设为静态,以便只制作一份副本。现在在 Print 对象上同步,我使用了一个布尔标志,这样当奇数线程打印一个奇数时,它将被发送到等待状态,同时通知偶数线程执行。逻辑的编写方式是,无论发生什么情况,奇数线程总是首先打印奇数,因为标志设置为 false 最初会阻止偶数线程执行并将其发送到等待状态。

            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
    

    【讨论】:

      【解决方案4】:

      您的问题是您正在创建 Thread 类的两个实例。因此,当调用 wait() 时,它位于两个不同的实例上,它们都没有另一个线程在争夺您的监视器,也没有另一个线程可以调用 notifyAll() 以将线程从其等待状态中唤醒。

      因此,您启动的每个线程将永远等待(或直到因其他原因而中断)。

      您希望多个线程访问同一个监视器,因此首先尝试编写一些代码,其中相关代码实际上不是线程,而只是被线程使用。

      @normalocity 已经提供了多个示例的链接。

      【讨论】:

        【解决方案5】:

        我刚刚更新了this answer 以包含SCCE。

        工人在 WorkerPauseManager 上调用 pauseIfNeeded。如果管理器在工作线程调用 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();
                }
            }
        }
        

        【讨论】:

          【解决方案6】:

          wait 方法的作用是,当某个线程通过锁定某个对象(我们称该对象为“a”)执行同步块时,然后在该同步块中,当线程执行对象“a”的等待方法时,像这样

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

          然后a对象将释放,线程必须进入等待状态,直到它从该状态释放。

          另一个线程现在可以使用一个对象,因为它是一个释放对象。因此,如果另一个线程锁定了该对象并执行了该对象的通知方法,例如

           a.notify ()
          

          然后可以从等待状态中释放由对象“a”进入等待状态的线程之一。否则,当调用 notifyAll 时,所有线程对象都将从该状态中释放。

          【讨论】:

            【解决方案7】:
            /*
             *  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();
                        }
                    }
                }
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2017-08-11
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-02-19
              • 1970-01-01
              • 2016-03-21
              相关资源
              最近更新 更多