質問

Following code is copied from http://www.programcreek.com/2009/02/notify-and-wait-example/

I have seen quite a few examples using a while loop to wrap a wait()

My question: In my first attempt to tackle similar problems, I was using a if statement to wrap the wait(). For example,

if(messages.size() == MAXQUEUE) {
        wait();
    }

What is the advantage for using while loop instead of if statement?

import java.util.Vector;

class Producer extends Thread {

    static final int MAXQUEUE = 5;
    private Vector messages = new Vector();

    @Override
    public void run() {
        try {
            while (true) {
                putMessage();
                //sleep(5000);
            }
        } catch (InterruptedException e) {
        }
    }

    private synchronized void putMessage() throws InterruptedException {
        while (messages.size() == MAXQUEUE) {
            wait();
        }
        messages.addElement(new java.util.Date().toString());
        System.out.println("put message");
        notify();
        //Later, when the necessary event happens, the thread that is running it calls notify() from a block synchronized on the same object.
    }

    // Called by Consumer
    public synchronized String getMessage() throws InterruptedException {
        notify();
        while (messages.size() == 0) {
            wait();//By executing wait() from a synchronized block, a thread gives up its hold on the lock and goes to sleep.
        }
        String message = (String) messages.firstElement();
        messages.removeElement(message);
        return message;
    }
}

class Consumer extends Thread {

    Producer producer;

    Consumer(Producer p) {
        producer = p;
    }

    @Override
    public void run() {
        try {
            while (true) {
                String message = producer.getMessage();
                System.out.println("Got message: " + message);
                //sleep(200);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String args[]) {
        Producer producer = new Producer();
        producer.start();
        new Consumer(producer).start();
    }
}
役に立ちましたか?

解決

It is possible that wait() returns even though the object that is being waited on was not actively notified by you (this is called "spurious wakeup" in the documentation). That's why it makes more sense to wrap the wait()-call into a while loop that checks whether the actual condition that you want to wait for is satisfied and calls wait() again if it's not, rather than simply assuming that when wait() returns the event you are actually waiting for has occured.

他のヒント

When wait is notified it will come out of if loop and execution will start. while is better here as even if wait is notified but the Queue is full, it should not go ahead. So it will keep waiting until Queue is empty. I hope it answers your question.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top