Java tutorial
public class ObjectFIFOTest extends Object { private static void fullCheck(ObjectFIFO fifo) { try { // Sync'd to allow messages to print while // condition is still true. synchronized (fifo) { while (true) { fifo.waitUntilFull(); print("FULL"); fifo.waitWhileFull(); print("NO LONGER FULL"); } } } catch (InterruptedException ix) { return; } } private static void emptyCheck(ObjectFIFO fifo) { try { // Sync'd to allow messages to print while // condition is still true. synchronized (fifo) { while (true) { fifo.waitUntilEmpty(); print("EMPTY"); fifo.waitWhileEmpty(); print("NO LONGER EMPTY"); } } } catch (InterruptedException ix) { return; } } private static void consumer(ObjectFIFO fifo) { try { print("just entered consumer()"); for (int i = 0; i < 3; i++) { synchronized (fifo) { Object obj = fifo.remove(); print("DATA-OUT - did remove(), obj=" + obj); } Thread.sleep(3000); } synchronized (fifo) { boolean resultOfWait = fifo.waitUntilEmpty(500); print("did waitUntilEmpty(500), resultOfWait=" + resultOfWait + ", getSize()=" + fifo.getSize()); } for (int i = 0; i < 3; i++) { synchronized (fifo) { Object[] list = fifo.removeAll(); print("did removeAll(), list.length=" + list.length); for (int j = 0; j < list.length; j++) { print("DATA-OUT - list[" + j + "]=" + list[j]); } } Thread.sleep(100); } for (int i = 0; i < 3; i++) { synchronized (fifo) { Object[] list = fifo.removeAtLeastOne(); print("did removeAtLeastOne(), list.length=" + list.length); for (int j = 0; j < list.length; j++) { print("DATA-OUT - list[" + j + "]=" + list[j]); } } Thread.sleep(1000); } while (!fifo.isEmpty()) { synchronized (fifo) { Object obj = fifo.remove(); print("DATA-OUT - did remove(), obj=" + obj); } Thread.sleep(1000); } print("leaving consumer()"); } catch (InterruptedException ix) { return; } } private static void producer(ObjectFIFO fifo) { try { print("just entered producer()"); int count = 0; Object obj0 = new Integer(count); count++; synchronized (fifo) { fifo.add(obj0); print("DATA-IN - did add(), obj0=" + obj0); boolean resultOfWait = fifo.waitUntilEmpty(500); print("did waitUntilEmpty(500), resultOfWait=" + resultOfWait + ", getSize()=" + fifo.getSize()); } for (int i = 0; i < 10; i++) { Object obj = new Integer(count); count++; synchronized (fifo) { fifo.add(obj); print("DATA-IN - did add(), obj=" + obj); } Thread.sleep(1000); } Thread.sleep(2000); Object obj = new Integer(count); count++; synchronized (fifo) { fifo.add(obj); print("DATA-IN - did add(), obj=" + obj); } Thread.sleep(500); Integer[] list1 = new Integer[3]; for (int i = 0; i < list1.length; i++) { list1[i] = new Integer(count); count++; } synchronized (fifo) { fifo.addEach(list1); print("did addEach(), list1.length=" + list1.length); } Integer[] list2 = new Integer[8]; for (int i = 0; i < list2.length; i++) { list2[i] = new Integer(count); count++; } synchronized (fifo) { fifo.addEach(list2); print("did addEach(), list2.length=" + list2.length); } synchronized (fifo) { fifo.waitUntilEmpty(); print("fifo.isEmpty()=" + fifo.isEmpty()); } print("leaving producer()"); } catch (InterruptedException ix) { return; } } private static synchronized void print(String msg) { System.out.println(Thread.currentThread().getName() + ": " + msg); } public static void main(String[] args) { final ObjectFIFO fifo = new ObjectFIFO(5); Runnable fullCheckRunnable = new Runnable() { public void run() { fullCheck(fifo); } }; Thread fullCheckThread = new Thread(fullCheckRunnable, "fchk"); fullCheckThread.setPriority(9); fullCheckThread.setDaemon(true); // die automatically fullCheckThread.start(); Runnable emptyCheckRunnable = new Runnable() { public void run() { emptyCheck(fifo); } }; Thread emptyCheckThread = new Thread(emptyCheckRunnable, "echk"); emptyCheckThread.setPriority(8); emptyCheckThread.setDaemon(true); // die automatically emptyCheckThread.start(); Runnable consumerRunnable = new Runnable() { public void run() { consumer(fifo); } }; Thread consumerThread = new Thread(consumerRunnable, "cons"); consumerThread.setPriority(7); consumerThread.start(); Runnable producerRunnable = new Runnable() { public void run() { producer(fifo); } }; Thread producerThread = new Thread(producerRunnable, "prod"); producerThread.setPriority(6); producerThread.start(); } } class ObjectFIFO extends Object { private Object[] queue; private int capacity; private int size; private int head; private int tail; public ObjectFIFO(int cap) { capacity = (cap > 0) ? cap : 1; // at least 1 queue = new Object[capacity]; head = 0; tail = 0; size = 0; } public int getCapacity() { return capacity; } public synchronized int getSize() { return size; } public synchronized boolean isEmpty() { return (size == 0); } public synchronized boolean isFull() { return (size == capacity); } public synchronized void add(Object obj) throws InterruptedException { waitWhileFull(); queue[head] = obj; head = (head + 1) % capacity; size++; notifyAll(); // let any waiting threads know about change } public synchronized void addEach(Object[] list) throws InterruptedException { // // You might want to code a more efficient // implementation here ... (see ByteFIFO.java) // for (int i = 0; i < list.length; i++) { add(list[i]); } } public synchronized Object remove() throws InterruptedException { waitWhileEmpty(); Object obj = queue[tail]; // don't block GC by keeping unnecessary reference queue[tail] = null; tail = (tail + 1) % capacity; size--; notifyAll(); // let any waiting threads know about change return obj; } public synchronized Object[] removeAll() throws InterruptedException { // // You might want to code a more efficient // implementation here ... (see ByteFIFO.java) // Object[] list = new Object[size]; // use the current size for (int i = 0; i < list.length; i++) { list[i] = remove(); } // if FIFO was empty, a zero-length array is returned return list; } public synchronized Object[] removeAtLeastOne() throws InterruptedException { waitWhileEmpty(); // wait for a least one to be in FIFO return removeAll(); } public synchronized boolean waitUntilEmpty(long msTimeout) throws InterruptedException { if (msTimeout == 0L) { waitUntilEmpty(); // use other method return true; } // wait only for the specified amount of time long endTime = System.currentTimeMillis() + msTimeout; long msRemaining = msTimeout; while (!isEmpty() && (msRemaining > 0L)) { wait(msRemaining); msRemaining = endTime - System.currentTimeMillis(); } // May have timed out, or may have met condition, // calc return value. return isEmpty(); } public synchronized void waitUntilEmpty() throws InterruptedException { while (!isEmpty()) { wait(); } } public synchronized void waitWhileEmpty() throws InterruptedException { while (isEmpty()) { wait(); } } public synchronized void waitUntilFull() throws InterruptedException { while (!isFull()) { wait(); } } public synchronized void waitWhileFull() throws InterruptedException { while (isFull()) { wait(); } } }