Java Concurrency Model - Part I - Producer Consumer Problem

Note: Get the source code from https://gitlab.com/som.mukhopadhyay/ProducerConsumer

As i was getting ready to teach Java Concurrency Model to my students, I have come up with few examples which i would like to share with you. The first example is about Producer Consumer problem. Here is the solution to this using wait and notify. In the next two posts we will see about CountDownLatch and FutureTask respectively.

Class ProducerConsumerQueue

Here's the formatted version of the ProducerConsumerQueue class:

package com.somitsolutions.training.java.ProducerConsumerProblem;

import java.util.Vector;

public class ProducerConsumerQueue {
    Vector<Integer> sharedQueue = new Vector<>();
    private final int SIZE = 4;

    public ProducerConsumerQueue() { }

    public int getSIZE() {
        return SIZE;
    }

    public synchronized void produce(int i) throws InterruptedException {
        while (sharedQueue.size() == SIZE) {
            System.out.println("Queue is full. " + Thread.currentThread().getName() + " is waiting, size = " + sharedQueue.size());
            wait();
        }
        sharedQueue.add(i);
        notifyAll();
    }

    public synchronized int consume() throws InterruptedException {
        while (sharedQueue.isEmpty()) {
            System.out.println("Queue is empty. " + Thread.currentThread().getName() + " is waiting, size: " + sharedQueue.size());
            wait();
        }
        int retVal = sharedQueue.remove(0);
        notifyAll();
        return retVal;
    }
}

Class Producer

package com.somitsolutions.training.java.ProducerConsumerProblem;

public class Producer implements Runnable {
    private final ProducerConsumerQueue sharedQueue;
    private final int SIZE;

    public Producer(ProducerConsumerQueue queue) {
        sharedQueue = queue;
        this.SIZE = sharedQueue.getSIZE();
    }

    @Override
    public void run() {
        for (int i = 0; i < 7; i++) {
            System.out.println("Produced: " + i);
            try {
                sharedQueue.produce(i);
                Thread.sleep(100);
            } catch (InterruptedException ex) {
                // Handle exception
            }
        }
    }
}

Class Consumer

Here's the formatted version of the Consumer class:

package com.somitsolutions.training.java.ProducerConsumerProblem;

public class Consumer implements Runnable {
    private final ProducerConsumerQueue sharedQueue;
    private final int SIZE;

    public Consumer(ProducerConsumerQueue queue) {
        sharedQueue = queue;
        this.SIZE = sharedQueue.getSIZE();
    }

    @Override
    public void run() {
        while (true) {
            try {
                int val = sharedQueue.consume();
                System.out.println("Consumed: " + val);
                Thread.sleep(50);
            } catch (InterruptedException ex) {
                // Handle exception
            }
        }
    }
}

Class Main

package com.somitsolutions.training.java.ProducerConsumerProblem;

public class Main {
    public static void main(String[] args) {
        ProducerConsumerQueue sharedQueue = new ProducerConsumerQueue();
        Thread prodThread = new Thread(new Producer(sharedQueue), "Producer");
        Thread consThread = new Thread(new Consumer(sharedQueue), "Consumer");

        prodThread.start();
        consThread.start();
    }
}
0
Subscribe to my newsletter

Read articles from Somenath Mukhopadhyay directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Somenath Mukhopadhyay
Somenath Mukhopadhyay

To win is no more than this... To rise each time you fall...