一个很好的小例子来演示java中的wait()和notify()方法

发布于 2024-12-19 08:42:30 字数 1180 浏览 6 评论 0 原文

任何人都可以给我提供一个很好的小例子来演示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 应该执行。请帮我解决这个问题。

Can anybody please provide me a good small example demonstrate wait() and notify() functionality in java. I've tried with the below piece of code but it's not showing what i expected.

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) {

            }

        }
    }
}

The issue is that the method in the class WaitDemo is not getting executed and as per my idea the SOP after wait() should execute. Please help me out on this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

栀梦 2024-12-26 08:42:30

下面是 wait & 的示例在 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();
    }

}

Below is an example of wait & notify in the Object class. The customer is trying to withdraw money of value 2000 but the account is having only 1000 so it has to wait for the deposit. Once the deposit is made, then the customer will be able to withdraw the amount. Until the deposit is made, the customer will be waiting.

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

}
伊面 2024-12-26 08:42:30

您的 try 块中有两层大括号 {。如果删除内部集(它似乎没有执行任何操作),是否可以解决问题?

周围有几个示例,所有这些示例都演示了其用法。最后一个链接是一组可以帮助您的结果。如果您需要更具体的事情,请让我知道您的应用程序正在尝试做什么,我可以尝试找到更适合您情况的示例。

You've got two levels of braces { in your try block. If you remove the inner set (which doesn't appear to do anything), does that fix the problem?

There are several examples around, all of which demonstrate the use. The last link is a set of results that can help you out. If you need more specific things, let me know what it is that your app is trying to do, and I can try to find examples that are more specific to your situation.

踏月而来 2024-12-26 08:42:30

我创建了两个线程,一个用于打印奇数 (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

I created two threads one for printing odd numbers (OddThread) and another for even numbers (EvenThread). Inside the run method of each of the threads I used the shared object of class Print to call printOdd() and printEven() for the Odd and EvenThread respectively. I made the shared object of Print static so that only one copy is made. Now synchronizing on the Print object I used a Boolean flag such that when the odd thread printed an odd number it will be sent into the waiting state and the at the same time notifying the even thread to execute. The logic is written in such a way that the odd thread will always print the odd number first no matter what, as the flag is set to false initially preventing the even thread to execute and sending it to a waiting state.

        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
活雷疯 2024-12-26 08:42:30

wait方法的作用是,当某个线程通过锁定某个对象(我们称该对象为“a”)来执行同步块时,然后在该同步块内,当线程执行对象“a”的wait方法时,如下

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

所示对象将被释放,并且线程必须进入等待状态,直到它从该状态释放。

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

 a.notify ()

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

What wait method does is , when some thread executed a synchronized block by locking some object (we call that object is "a") , then inside that synchronized block when the thread executed the wait method of object "a" like this

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

Then the a object will release and the thread has to go to the wait state until it has been release from that state.

and anothet thread now can use the a object beacause its a release object. so if another thread locked that object and it executed the notify method from that object like

 a.notify ()

Then one of a thread of the threads that went to wait state by object "a" can be released from the wait state. Other wise when call the notifyAll then the all the thread objects will release from that state.

这样的小城市 2024-12-26 08:42:30

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

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

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

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

Your problem is that you are creating two instances of the Thread class. Thus when the wait() is called, it is on two different instances, neither of which has another thread that is in contention for your monitor, nor is there another thread to call notifyAll() to wake the thread from its wait state.

Thus each thread you have started will wait forever (or until interrupted for some other reason).

You want to have multiple threads accessing the same monitor, so start by trying to code something in which the code in question is not actually a thread, but is simply being used by a thread.

@normalocity has already provided links to multiple examples.

简单 2024-12-26 08:42:30

我刚刚更新了此答案以包含SCCE

工作人员在 WorkerPauseManager 上调用pauseIfNeeded。如果管理器在工作线程调用pauseIfNeeded()时暂停,我们将调用wait(),它告诉调用线程等待,直到另一个线程对正在等待的对象调用notify()或notifyAll()。当 Swing 事件调度线程调用管理器上的 play() 时,就会发生这种情况,而管理器又调用 notificationAll()。

请注意,您必须在调用 wait() 或 notification() 的对象上拥有同步锁。由于 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();
        }
    }
}

I just updated this answer to include an SCCE.

The workers call pauseIfNeeded on the WorkerPauseManager. If the manager is paused when the worker thread calls pauseIfNeeded(), we call wait(), which tells the calling thread to wait until a different thread calls notify() or notifyAll() on the object being waited on. This happens when the Swing Event Dispatch Thread calls play() on the manager, which in turn calls notifyAll().

Note that you must have a synchronized lock on the object you are calling wait() or notify() on. Since the methods in WorkerPauseManager are synchronized, all the synchronized methods are getting a synchronized lock on the WorkerPauseManager itself.

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();
        }
    }
}
亽野灬性zι浪 2024-12-26 08:42:30
/*
 *  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();
            }
        }
    }
}
/*
 *  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();
            }
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文