ObjectFIFOTest.java Source code

Java tutorial

Introduction

Here is the source code for ObjectFIFOTest.java

Source

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();
        }
    }
}