8

谁能给我一个很好的小例子来演示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 应该执行。请帮我解决这个问题。

4

7 回答 7

3

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

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

于 2011-12-02T15:30:24.507 回答
3

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

}
于 2015-10-23T09:43:49.573 回答
1

我创建了两个线程,一个用于打印奇数(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
于 2016-03-22T14:08:42.970 回答
0

我刚刚更新了这个答案以包含一个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();
        }
    }
}
于 2011-12-02T16:44:03.283 回答
0

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

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

你想让多个线程访问同一个监视器,所以首先尝试编写一些代码,其中所讨论的代码实际上不是一个线程,而只是被一个线程使用。

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

于 2011-12-02T15:58:53.223 回答
0

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

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

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

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

 a.notify ()

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

于 2017-11-05T06:58:02.693 回答
-2
/*
 *  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();
            }
        }
    }
}
于 2012-10-01T11:49:52.420 回答