// 2 consumers - 2 producers
public class ProducerConsumer2 {
	public static void main(String args[]) {
		Buffer b = new Buffer();
		Producer p1 = new Producer("p1",b,0);
		Producer p2 = new Producer("p2",b,20);
		Consumer c1 = new Consumer("c1",b);
		Consumer c2 = new Consumer("c2",b);
		
		System.out.println("Ver2:2 producers - 2 consumers");
		p1.start();
		c1.start();
		p2.start();
		c2.start();
		}
	}
	
class Producer extends Thread {
	private int start;
	private Buffer b;
	
	public Producer(String tname,Buffer b, int start){super(tname);this.b = b;this.start = start;}
	
	public void run() {
		for(int i=start;i<start+10;i++) {
			try {
				Thread.sleep((int)(Math.random() * 3000));
				}
			catch(InterruptedException e) {
				System.err.println(e.toString());
				}
			b.put(i);
			System.out.println("Producer "+ getName()+" set buffer to " + i);
			}
		}	
	}
	
class Consumer extends Thread {
	private Buffer b;
	
	public Consumer(String tname,Buffer b){super(tname);this.b = b;}
	
	public void run() {
		for(int i=0;i<10;i++) {
			try {
				Thread.sleep((int)(Math.random() * 3000));
				}
			catch(InterruptedException e) {
				System.err.println(e.toString());
				}
			System.out.println("Consumer "+ getName()+" retrieved " + b.get());
			}
		}	
	}
	
class Buffer {
	private int value;
	private boolean empty = true;
	
	public synchronized void put(int val) {
		while(!empty) {
			try{
				wait();
				}
			catch(InterruptedException e) {
				System.err.println("Exception:" + e.toString()); 
				}
			}
		value = val;
		empty = false;
		notify();
		}
	
	public synchronized int get() {
		int value;
		
		while(empty) {
			try{
				wait();
				}
			catch(InterruptedException e) {
				System.err.println("Exception:" + e.toString()); 
				}
			}
		value = this.value;
		empty = true;
		notify();
		return value;
		}
	}