/** * Class for bounded buffer, with synchronization. */ public class BoundedBuffer { private Object[] buffer; private int nextToRemove; private int numElements; public BoundedBuffer(int sz) { buffer = new Object[sz]; nextToRemove = 0; numElements = 0; } /** * Put item into buffer. * Waits if buffer is full; wakes up all waiting threads on exit. * Allows exceptions thrown by wait() to bubble up. */ public synchronized void put(Object o) throws InterruptedException { System.err.println("starting put with numElements = " + numElements); /* wait until not full */ while (numElements == buffer.length) wait(); int next = (nextToRemove + numElements) % buffer.length; buffer[next] = o; ++numElements; /* wake up any waiting threads, since some might be waiting * for "buffer not empty" */ notifyAll(); System.err.println("ending put with numElements = " + numElements); } /** * Get item from buffer. * Waits if buffer is empty; wakes up all waiting threads on exit. * Allows exceptions thrown by wait() to bubble up. * @return item */ public synchronized Object get() throws InterruptedException { System.err.println("starting get with numElements = " + numElements); /* wait until not empty */ while (numElements == 0) wait(); Object o = buffer[nextToRemove]; nextToRemove = (nextToRemove + 1) % buffer.length; --numElements; /* wake up any waiting threads, since some might be waiting * for "buffer not full" */ notifyAll(); System.err.println("ending get with numElements = " + numElements); return o; } /** * Check with buffer is empty. */ public synchronized boolean isEmpty() { return (numElements == 0); } }