Curriculum
Course: Learn Java Programming
Login

Curriculum

Learn Java Programming

Video lesson

Understanding the Producer and Consumer Problem in Java

 

In this lesson, you will learn.

  • Producer and Consumer Problem
  • Example

 

Producer and Consumer Problem

The producer-consumer problem is a classic example of a multi-threading problem involving synchronization.

It describes a scenario where one or more producer threads generate data and put it in a shared resource (like a buffer), while one or more consumer threads retrieve and process that data.

This shared buffer needs to be protected and managed carefully to avoid issues such as data corruption or deadlocks.

 

 

Components of the Problem

  1. Producers:
    • Producers generate items and add them to the shared buffer.
    • They must wait if the buffer is full to avoid overwriting or corrupting data.
  2. Consumers:
    • Consumers remove items from the shared buffer and process them.
    • They must wait if the buffer is empty to avoid consuming invalid data.
  3. Buffer (or Shared Resource):
    • Holds data produced by the producers until consumed by the consumers.
    • Should have a fixed capacity to avoid overflow or underflow.

 

Example

Consider the following example that incorrectly implements a simple form of Producer/Consumer problem.

It consists of 4 classes

  1. Q (Buffer): That you are trying to synchronize.
  2. Producer: A threaded object that produces an entry in ShareValue.
  3. Consumer: A threaded object that consumes an entry from a ShareValue.
  4. A Main Class

 

Example: An Incorrect Solution of Producer/Consumer Problem

package producerconsumerproblem.one;

//A correct implementation of a producer and consumer problem
class Q {
    private int value;
      
    // Producer will call this method to produce a value
    public synchronized void produce(int value) throws InterruptedException {
        this.value = value;
        System.out.println("Produced: " + value);     
    }

    // Consumer will call this method to consume a value
    public synchronized int consume() throws InterruptedException {
    	System.out.println("Consumed: " + value);
        return value;
    }
}

class Producer extends Thread {
    private final Q sharedValue;

    public Producer(Q sharedValue) {
        this.sharedValue = sharedValue;
    }

    @Override
    public void run() {
        int value = 0;
        try {
            while (true) {
                sharedValue.produce(value++);
                Thread.sleep(100); // Simulate time taken to produce
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

class Consumer extends Thread {
    private final Q sharedValue;

    public Consumer(Q sharedValue) {
        this.sharedValue = sharedValue;
    }

    @Override
    public void run() {
        try {
            while (true) {
                sharedValue.consume();
                Thread.sleep(150); // Simulate time taken to consume
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

public class ProducerConsumer {
    public static void main(String[] args) {
        Q sharedValue = new Q();
        //Creating instances of Producer and Consumer
        Producer producer = new Producer(sharedValue);
        Consumer consumer = new Consumer(sharedValue);
        //Start the thread
        producer.start();
        consumer.start();
    }
}

Output

Produced: 0
Consumed: 0
Produced: 1
Consumed: 1
Produced: 2
Consumed: 2
Produced: 3
Produced: 4
Consumed: 4
Produced: 5
Consumed: 5
Produced: 6
Produced: 7
Consumed: 7

 

Example: A Correct Solution of Producer/Consumer Problem

package producerconsumerproblem.two;

//A Correct Implementation of Producer and Consumer problem
class Q {
	private int value;
	private boolean isValueAvailable = false;

	// Producer will call this method to produce a value
	public synchronized void produce(int value) throws InterruptedException {
		// Wait until the consumer consumes the current value
		while (isValueAvailable) {
			wait();
		}
		this.value = value;
		System.out.println("Produced: " + value);
		isValueAvailable = true;
		// Notify the consumer thread that a value has been produced
		notify();
	}

	// Consumer will call this method to consume a value
	public synchronized int consume() throws InterruptedException {
		// Wait until the producer provides a new value
		while (!isValueAvailable) {
			wait();
		}
		System.out.println("Consumed: " + value);
		isValueAvailable = false;
		// Notify the producer thread that the value has been consumed
		notify();
		return value;
	}
}

class Producer extends Thread {
	private final Q sharedValue;

	public Producer(Q sharedValue) {
		this.sharedValue = sharedValue;
	}

	@Override
	public void run() {
		int value = 0;
		try {
			while (true) {
				sharedValue.produce(value++);
				Thread.sleep(100); // Simulate time taken to produce
			}
		} catch (InterruptedException e) {
			Thread.currentThread().interrupt();
		}
	}
}

class Consumer extends Thread {
	private final Q sharedValue;

	public Consumer(Q sharedValue) {
		this.sharedValue = sharedValue;
	}

	@Override
	public void run() {
		try {
			while (true) {
				sharedValue.consume();
				Thread.sleep(150); // Simulate time taken to consume
			}
		} catch (InterruptedException e) {
			Thread.currentThread().interrupt();
		}
	}
}

public class ProducerConsumer {
	public static void main(String[] args) {
		Q sharedValue = new Q();
		
		Producer producer = new Producer(sharedValue);
		Consumer consumer = new Consumer(sharedValue);
		//Starting both the thread
		producer.start();
		consumer.start();
	}
}

Output

Produced: 0
Consumed: 0
Produced: 1
Consumed: 1
Produced: 2
Consumed: 2
Produced: 3
Consumed: 3
Produced: 4
Consumed: 4
Produced: 5
Consumed: 5
Produced: 6
Consumed: 6

 

 

 


End of the lesson….enjoy learning

 

 

Student Ratings and Reviews

 

 

 

There are no reviews yet. Be the first one to write one.

 

 

Submit a Review