Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

wait() is a "if" block or a "while" block [duplicate]

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();
    }
}
like image 907
bookmonkie Avatar asked Dec 07 '22 02:12

bookmonkie


1 Answers

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.

like image 197
Markus A. Avatar answered Dec 08 '22 15:12

Markus A.