Write a Java program that correctly implements the producer – consumer problem using the concept of inter thread communication.
import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
public class ProducerConsumerProblem {
public static void main(String[] args) {
// Create a shared resource (the buffer) with a maximum capacity
final Buffer sharedBuffer = new Buffer(5);
// Create producer and consumer threads
Thread producerThread = new Thread(new Producer(sharedBuffer), "ProducerThread");
Thread consumerThread = new Thread(new Consumer(sharedBuffer), "ConsumerThread");
// Start both threads
producerThread.start();
consumerThread.start();
}
}
// The shared buffer class manages the queue and synchronization
class Buffer {
private final Queue<Integer> queue = new LinkedList<>();
private final int capacity;
public Buffer(int capacity) {
this.capacity = capacity;
}
// Method for the producer to add items
public synchronized void produce(int value) throws InterruptedException {
// Wait while the buffer is full
while (queue.size() == capacity) {
System.out.println("Buffer is full. Producer waiting...");
wait(); // Releases the lock and waits for a consumer to notify
}
// Add the item to the buffer
queue.add(value);
System.out.println("Producer produced: " + value + " | Current size: " + queue.size());
// Notify waiting consumers that an item is available
notifyAll();
}
// Method for the consumer to remove items
public synchronized int consume() throws InterruptedException {
// Wait while the buffer is empty
while (queue.size() == 0) {
System.out.println("Buffer is empty. Consumer waiting...");
wait(); // Releases the lock and waits for a producer to notify
}
// Remove the item from the buffer
int value = queue.poll();
System.out.println("Consumer consumed: " + value + " | Current size: " + queue.size());
// Notify waiting producers that space is available
notifyAll();
return value;
}
}
// The Producer runnable task
class Producer implements Runnable {
private final Buffer buffer;
private final Random random = new Random();
public Producer(Buffer buffer) {
this.buffer = buffer;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) { // Produce 10 items
try {
int value = random.nextInt(100);
buffer.produce(value);
Thread.sleep(random.nextInt(500)); // Simulate time taken to produce
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
// The Consumer runnable task
class Consumer implements Runnable {
private final Buffer buffer;
private final Random random = new Random();
public Consumer(Buffer buffer) {
this.buffer = buffer;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) { // Consume 10 items
try {
buffer.consume();
Thread.sleep(random.nextInt(1000)); // Simulate time taken to consume
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
Comments
Post a Comment