Search code examples
javamultithreadingwaitnotify

Java wait/notify - not waking up thread


I'm trying to do a small exercise to get used to wait/notify. What i'm trying to do is simply start a thread, then put it to sleep with wait and wake it up with notify, multiple times.

My code is:

public class Simple{
    static final Thread mainThread = Thread.currentThread();

    public static void main(String[] args) throws InterruptedException {
        PrintThread printer = new PrintThread(0);
        printer.start();

        synchronized (mainThread){
            System.out.println("main sleeping while waiting for printer to be started");
            mainThread.wait();
            System.out.println("main woke up");


            for (int i = 0; i < 1000; i++) {
                synchronized (printer){
                    System.out.println("added num "+i);
                    printer.numToPrint = i;
                    System.out.println("main waking up printer");
                    printer.notifyAll();
                    System.out.println("main sleeping");
                    mainThread.wait();
                    System.out.println("main woke up");
                }
            }

        }

    }
}

class PrintThread extends Thread{
    public int numToPrint = -1;

    public PrintThread(int numToPrint){
        this.numToPrint = numToPrint;
    }

    @Override
    public synchronized void run() {
        System.out.println("printer started");
        while (true){
            try {
                synchronized (Simple.mainThread){
                    System.out.println("printer waking up main");
                    Simple.mainThread.notifyAll();
                }
                System.out.println("printer sleeping");
                wait();
                System.out.println("printer woke up");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("printing num "+numToPrint);
        }
    }

}

I would expect this to go something like

main sleeping while waiting for printer to be started
printer started
printer waking up main
printer sleeping
main woke up
added num 0
main waking up printer
main sleeping
printer woke up
printing num 0
printer waking up main
printer sleeping
main woke up
added num 1
...

Instead this does:

main sleeping while waiting for printer to be started
printer started
printer waking up main
printer sleeping
main woke up
added num 0
main waking up printer
main sleeping

So... it seems like notify isn't waking up the printer thread?

It shouldn't be a deadlock since by waiting i realease all the locks i have, so the main shoudn't have any lock over printer and printer should be able to wake up and print.

What am i doing wrong?


Solution

  • Most likely your notifyAll() call is being called before Print calls wait() again. The problem is your reliance on the wait and notifyAll calls happening in exactly the sequence you'd like them to. These are two different threads of execution so of course this is not guaranteed, and thus you are getting what you've got.

    A MUCH better way to accomplish this would be to create a common 3rd shared object that both threads could acquire lock on. This would synchronize both threads as they wait to get access to this object.

    Also, you should read the Javadocs for Thread.wait, notify, and notifyAll. If/when you do, you will see that you should NEVER call these methods on Threads, as they are used in doing thread.join (Not only that, but my "claim to fame" is I believe it was my bug request years ago to document this when this wasn't in the JavaDoc that resulted in it being added to the Javadoc. Could have been someone else, but it happened right after I asked for it :))