//========================================================
// Fail TootjadTarbijad_Runnable.java
//========================================================

import java.util.*;

/** Tootja-tarbija ylesanne tehtud Runnable liidese abil. */

public class TootjadTarbijad_Runnable {

   static final int PUHVRIPIKKUS = 6;
   static Vector yhispuhver = new Vector (PUHVRIPIKKUS);

   /** peameetod. */
   public static void main (String[] parameetrid) {
      int tootja1_tiks  = 5000; //millisekundit
      int tootja2_tiks  = 7000; //millisekundit
      int tarbija1_tiks = 3000; //millisekundit
      System.out.println
         ("Puhvri suurus: " + yhispuhver.capacity());
      Tootja  tootja1  =
         new Tootja  (yhispuhver, tootja1_tiks,  "Pro1");
      Tootja  tootja2  =
         new Tootja  (yhispuhver, tootja2_tiks,  "Pro2");
      Tarbija tarbija1 =
         new Tarbija (yhispuhver, tarbija1_tiks, "Con1");
   } // main lopp

} // TootjadTarbijad_Runnable lopp

/** Tootja on Object, mis oskab Runnable liidest. */

class Tootja implements Runnable {

   /** yhispuhver toodete paigutamiseks. */
   Vector puhver;
 
   /** toote tootmiseks kuluv aeg millisekundites. */
   int tiks;

   /** tootja kaubama"rk. */
   String nimi;

   /** tootja ise ei ole lo'im, ta sisaldab lo'ime. */
   Thread loim;

   /** konstruktor. */
   Tootja (Vector v, int i, String s) {
      puhver = v;
      tiks = i;
      nimi = s;
      loim = new Thread(this); // this on meil Runnable!
      loim.start();  // loomine sisaldab ka ka"ivitamise
   }

   /** rahuldame liidese Runnable. */
   public void run() {
      try {
         while (true) { //lopmatu tsykkel
            tooda();    //iga tiksuga toodab uue asja
            loim.sleep (tiks);
         }
      }
      catch (InterruptedException e) {
      }
   }

   /** yhe toote tootmine. */
   private void tooda()
      throws InterruptedException {
         synchronized (puhver) {
            while (puhver.size() >= puhver.capacity()) {
               puhver.wait(); //puhver on ta"is, oota
            }
            puhver.addElement ("(" + nimi + " > " +
               new Date().toString() + ")"); //ajatempel
            System.out.println (nimi + " > " + 
               puhver.lastElement() +
               " " + tiks + " " + puhver.size());
            puhver.notifyAll();
         } // kriitilise sektsiooni lopp
   }
} // Tootja lopp

/** Tarbija on symmeetriline Tootjaga - Runnable Object. */

class Tarbija implements Runnable {
   Vector puhver;
   int tiks;
   String nimi;
   Thread loim;

   Tarbija (Vector v, int i, String s) {
      puhver = v;
      tiks = i;
      nimi = s;
      loim = new Thread (this);
      loim.start();
   }

   /** see meetod teebki meie objekti Runnable objektiks. */
   public void run() {
      try {
         while (true) { //lopmatu tsykkel
            tarbi();    //iga tiksuga tarbib u"he asja
            loim.sleep (tiks);
         }
      }
      catch (InterruptedException e) {
      }
   }

   /** yhe toote tarbimine. */
   private void tarbi()
      throws InterruptedException {
         synchronized (puhver) {
            while (puhver.size() <= 0) {
               puhver.wait(); //oota, kuni midagi tekib
            }
            String teade = (String)puhver.firstElement();
            System.out.println (nimi + " < " +
               teade + " " + tiks);
            puhver.removeElementAt (0);
            puhver.notifyAll();
         } // kriitilise sektsiooni lopp
   }
} // Tarbija lopp

//====================
// faili lopp 
//====================
