

/**
 * Aum Amriteswaryai Namah
 * @author Kishor Kamath
 */

//enum Action {T, E, H};
//enum Action {T, E, H};

public class DiningPhilosophers {
    public static void main(String[] args) throws InterruptedException
    {
        Fork c1 = new Fork(1);
        Fork c2 = new Fork(2);
        Fork c3 = new Fork(3);
        
        Philosopher p1 = new Philosopher("P1",c1,c3);
        Philosopher p2 = new Philosopher("P2",c2,c1);
        Philosopher p3 = new Philosopher("P3",c3,c2);
        
        p1.start();
        p2.start();
        p3.start();
    }
}

class Philosopher extends Thread {
    String name;
    char action;
    Fork left, right;
    Philosopher(String name,Fork left,Fork right)
    {
        this.name = name;
        this.left = left;
        this.right = right;
        action = 'T';
        System.out.println("Philosopher "+ name+" : Thinking");
    }
    void feelHungry() throws Exception
    {    	
     	action = 'H';        
        System.out.println("Philosopher "+ name+" : Hungry");
    }
    void pickUp() throws Exception
    {
        left.get(); 
        right.get();
        System.out.println("Philosopher "+ name+" : Eating");
        action = 'E';
        
    }
    void putDown()
    {
    	System.out.println("Philosopher "+ name+" : Thinking");
    	
        left.put();           
        right.put();
        action = 'T';
        
        
    }
    //@Override
    public void run()
    {
    	try{
        for(int i=0; i<10; i++)
        {
        	sleep((int)(500*Math.random()));
            feelHungry();
            pickUp();            
           sleep((int)(600*Math.random()));
            putDown();
        }
        }catch(Exception e){}
    }
}

class Fork {
    /**
     * @param args the command line arguments
     */
    boolean taken = false;
    int id;
    Fork(int id)
    {
        this.id = id;
    }
    int getID()
    {
        return id;
    }
    synchronized void get() throws Exception
    {
        while(taken)
            wait();
        taken = true;
    }
    synchronized void put()
    {
        taken = false;
        notify();
    }
}   
