Example Waiting and Notifying

class StackImpl {
    private Object[] stackArray;
    private volatile int topOfStack;

    StackImpl (int capacity) {
        stackArray = new Object[capacity];
        topOfStack = -1;
    }

    public synchronized Object pop() {
        System.out.println(Thread.currentThread() + ": popping");
        while (isEmpty())
            try {
                System.out.println(Thread.currentThread() + ": waiting to pop");
                wait();                             // (1)
            } catch (InterruptedException e) { }
        Object obj = stackArray[topOfStack];
        stackArray[topOfStack--] = null;
        System.out.println(Thread.currentThread() + ": notifying after pop");
        notify();                                   // (2)
        return obj;
    }

    public synchronized void push(Object element) {
        System.out.println(Thread.currentThread() + ": pushing");
        while (isFull())
            try {
                System.out.println(Thread.currentThread() + ": waiting to push");
                wait();                             // (3)
            } catch (InterruptedException e) { }
        stackArray[++topOfStack] = element;
        System.out.println(Thread.currentThread() + ": notifying after push");
        notify();                                   // (4)
    }

    public boolean isFull() { return topOfStack >= stackArray.length -1; }
    public boolean isEmpty() { return topOfStack < 0; }
}

abstract class StackUser extends Thread {           // (5) Stack user

    protected StackImpl stack;                      // (6)

    StackUser(String threadName, StackImpl stack) {
        super(threadName);
        this.stack = stack;
        System.out.println(this);
        setDaemon(true);                            // (7) Daemon thread
        start();                                    // (8) Start this thread.
    }
}
class StackPopper extends StackUser {               // (9) Popper
    StackPopper(String threadName, StackImpl stack) {
        super(threadName, stack);
    }
    public void run() { while (true) stack.pop(); }
}

class StackPusher extends StackUser {               // (10) Pusher
    StackPusher(String threadName, StackImpl stack) {
        super(threadName, stack);
    }
    public void run() { while (true) stack.push(new Integer(1)); }
}

public class WaitAndNotifyClient {
    public static void main(String[] args)
           throws InterruptedException {            // (11)

        StackImpl stack = new StackImpl(5);

        new StackPusher("A", stack);
        new StackPusher("B", stack);
        new StackPopper("C", stack);
        System.out.println("Main Thread sleeping.");
        Thread.sleep(1000);
        System.out.println("Exit from Main Thread.");
    }
}
Possible output from the program:
Thread[A,5,main]
Thread[B,5,main]
Thread[C,5,main]
Main Thread sleeping.
...
Thread[A,5,main]: pushing
Thread[A,5,main]: waiting to push
Thread[B,5,main]: pushing
Thread[B,5,main]: waiting to push
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[A,5,main]: notifying after push
Thread[A,5,main]: pushing
Thread[A,5,main]: waiting to push
Thread[B,5,main]: waiting to push
Thread[C,5,main]: popping
Thread[C,5,main]: notifying after pop
Thread[A,5,main]: notifying after push
...
Thread[B,5,main]: notifying after push
...
Exit from Main Thread.
...

No comments:

Post a Comment