/*   Producers-Consumers           */
/*   Multithreads implementation   */
 
/*   File Producers_Consumers.java */
 
/* Main program */
 
public class prova1 {
  public static void main(String[] args) {
    Buffer b = new Buffer();
    new Producer(b,1).start();
    new Producer(b,2).start();
    new Producer(b,3).start();
    new Consumer(b,1).start();
    new Consumer(b,2).start();
  }
}

class Producer extends Thread {
  private Buffer buff;
  private int id;
  public Producer(Buffer b, int n) { buff = b; id = n; }
  public void run() {
    try {
      for (;;) {
        sleep((long)(java.lang.Math.random()*10)); 
        buff.put(id);
      }
    } catch (InterruptedException e) { return; }
  }
}

class Consumer extends Thread {
  private Buffer buff;
  private int id;
  public Consumer(Buffer b, int n) { buff = b; id = n; }
  public void run() {
    try {
      for (;;) {
        sleep((long)(java.lang.Math.random()*10)); 
        int k = buff.get(id);
        System.out.println("consumer " + id + " has retrieved the datum put by producer " + k);
      }
    } catch (InterruptedException e) { return; }
  }
}

class Buffer {
  private int content;
  private boolean is_empty;
  public Buffer() { is_empty = true; }
  public synchronized void put(int k) 
    throws InterruptedException
  {    
    while (!is_empty) { 
      System.out.println("producer" + k + " has to wait");
      wait(); 
      System.out.println("producer" + k + " has been notified");
    }
    content = k;
    is_empty = false;
    System.out.println("producer" + k + " has put its datum in the buffer");
    //System.out.println("producer" + k + " going to sleep");
    //Thread.currentThread().sleep((long)(java.lang.Math.random()*1000)); 
    //System.out.println("producer" + k + " returning from sleep");
    notify();
    System.out.println("producer" + k + " has sent notification");
  }
  public synchronized int get(int ide) 
    throws InterruptedException
  {
    while (is_empty) { 
      System.out.println("consumer" + ide + " has to wait");
      wait(); 
      System.out.println("consumer" + ide + " has been notified");
    }
    is_empty = true;
    //System.out.println("consumer" + ide + " going to sleep");
    //Thread.currentThread().sleep((long)(java.lang.Math.random()*1000)); 
    //System.out.println("consumer" + ide + " returning from sleep");
    notify();
    System.out.println("consumer" + ide + " has sent notification");
    return content;
  }
}
  
