import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class BoundedBuffer {
private final Queue<String> buffer;
private final int capacity;
private final Lock lock = new ReentrantLock();
private final Condition notFull = lock.newCondition();
private final Condition notEmpty = lock.newCondition();
public BoundedBuffer(int capacity) {
this.buffer = new LinkedList<>();
this.capacity = capacity;
}
public void put(String message) throws InterruptedException {
lock.lock();
try {
while (buffer.size() == capacity) {
notFull.await();
}
buffer.add(message);
notEmpty.signal();
} finally {
lock.unlock();
}
}
public String get() throws InterruptedException {
lock.lock();
try {
while (buffer.isEmpty()) {
notEmpty.await();
}
String message = buffer.remove();
notFull.signal();
return message;
} finally {
lock.unlock();
}
}
}
class Producer implements Runnable {
private final BoundedBuffer buffer;
private final int id;
private final Random random = new Random();
Producer(BoundedBuffer buffer, int id) {
this.buffer = buffer;
this.id = id;
}
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
String message = "Message " + i + " from Producer " + id;
buffer.put(message);
Thread.sleep(random.nextInt(1000));
}
buffer.put("Bye");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
class Consumer implements Runnable {
private final BoundedBuffer buffer;
private final int id;
private final Random random = new Random();
Consumer(BoundedBuffer buffer, int id) {
this.buffer = buffer;
this.id = id;
}
@Override
public void run() {
try {
while (true) {
String message = buffer.get();
System.out.println("Consumer " + id + ": " + message);
if ("Bye".equals(message)) {
break;
}
Thread.sleep(random.nextInt(100));
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
public class ProducerConsumerDemo {
private static final int BUFFER_SIZE = 32;
private static final int NUM_PRODUCERS = 2;
private static final int NUM_CONSUMERS = 2;
public static void main(String[] args) throws InterruptedException {
BoundedBuffer buffer = new BoundedBuffer(BUFFER_SIZE);
Thread[] producers = new Thread[NUM_PRODUCERS];
Thread[] consumers = new Thread[NUM_CONSUMERS];
for (int i = 0; i < NUM_PRODUCERS; i++) {
producers[i] = new Thread(new Producer(buffer, i));
producers[i].start();
}
for (int i = 0; i < NUM_CONSUMERS; i++) {
consumers[i] = new Thread(new Consumer(buffer, i));
consumers[i].start();
}
for (Thread producer : producers) {
producer.join();
}
for (Thread consumer : consumers) {
consumer.join();
}
}
}