Search code examples
javamultithreadingsynchronizationqueueproducer-consumer

Java synchronized queue thread on producer and consumer


Java producer-consumer program using thread & synchronized queue, the program is separated into 3 classes but it couldn't be run.

Queue.java:

public class Queue {
    static final int MAXQUEUE = 3;
    int[] queue = new int[MAXQUEUE];
    int front, rear;
    public Queue(){ front = 0; rear = 0; }
    public boolean isEmpty(){ return (front==rear); }

    public boolean isFull(){
        int index = rear+1 < MAXQUEUE ? rear+1 : 0;
        return (index == front);
    }

    public void enqueue(int value) {
        queue[rear] = value;
        rear = rear+1 < MAXQUEUE ? rear+1 : 0; 
    }

    public int dequeue(){
        int data = queue[front];
        front = front+1 < MAXQUEUE ? rear+1 : 0;
        return data;
    }
}

SynchronizedQueue.java:

import java.util.Queue;

public class SynchronizedQueue {
    Queue queue;
    public SynchronizedQueue() {queue = new Queue(); }
    public synchronized void enqueue(int value) {
        try {
            while (queue.isFull()) {
                System.out.println();
                System.out.println("Queue is full, please wait....");
                wait();
            }
        }
        catch (InterruptedException e) { }
        ((SynchronizedQueue) queue).enqueue(value);
        notify();
    }
    public synchronized int dequeue() {
        try {
            while (queue.isEmpty()) {
                System.out.println();
                System.out.println("Queue is empty, please wait....");
                wait();
            }
        }
        catch ( InterruptedException e ) { }
        int data = ((SynchronizedQueue) queue).dequeue();
        notify();
        return data;
    }
}

Main program Ch10_3.java:

class Producer extends Thread {
    public int count = 0;
    public void run() {
        int value;
        while ( Ch10_3.isRunning ) {
            value = (int)(Math.random()*100);
            Ch10_3.squeue.enqueue(value);
            System.out.print(">" + value + "]");
            count++;
            try {
                Thread.sleep((int)(Math.random()*100));
            }
            catch( InterruptedException e) { }
        }
        System.out.println("\n" + Thread.currentThread() + "Producer thread end.");
    }
}

class Consumer extends Thread {
    public int count = 0;
    public void run() {
        int data;
        while (Ch10_3.isRunning) {
            data = Ch10_3.squeue.dequeue();
            System.out.println("[" + data + ">");
            count++;
            try {
                Thread.sleep((int)(Math.random()*100));
            }
            catch( InterruptedException e) { }
        }
        System.out.println("\n" + Thread.currentThread() + "Consumer thread end.");
    }
}

public class Ch10_3 {
    static final int MAXITEMS = 10;
    static SynchonizedQueue squeue = new SynchronizedQueue();
    static boolean isRunning = true;

    public static void main(String[] args) {
        Producer producer = new Producer();
        Consumer consumer = new Consumer();

        producer.start();   consumer.start();
        while (true)
            if (producer.count >= MAXITEMS && producer.count == consumer.count)
            {   isRunning = false;  break; }
    }
}

Error message:

Exception in thread "main" java.lang.Error: Unresolved compilation problem: at Ch10_3.main(Ch10_3.java:41)


Solution

  • In the catch blocks from enqueue and dequeue methods form class SynchronizedQueue you are trying to cast the queue member attribute which is of type Queue, to SynchronizedQueue.

    In SynchronizedQueue.enqueue() we have:

    ((SynchronizedQueue) queue).enqueue(value);
    

    Since there is no relation between Queue and SynchronizedQueue the compiler gives a compilation error. You should remove the cast.

    But the best solution is to just use a java.util.concurrent.BlockingQueue implementation available in JAVA SDK, which will handle all the synchronisation part for you.