import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class CenaFilosofos extends JFrame{
    private Tenedor tenedores[];
    private Filosofo filosofos[];
    AreaDibujo miAreaDibujo;
    
    CenaFilosofos() {
        tenedores = new Tenedor[5];
        filosofos = new Filosofo[5];
        miAreaDibujo = new AreaDibujo(); 
        
        int i, k;
        for(i=0; i<5; i++)
            tenedores[i] = new Tenedor();
        
        int coor[][] = {{200, 150}, {165, 197}, {109, 179}, {109, 120}, {165, 102}};
        
        for(i=0; i<5; i++) {
            k = i-1 < 0 ? 4 : i-1;
            filosofos[i] = new Filosofo(tenedores[k], tenedores[i], i, 
                    coor[i][0], coor[i][1]);
        }    
        
        add(miAreaDibujo);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
        pack();
        for(i=0; i<5; i++)
            filosofos[i].start();
    
    
    private class Filosofo extends Thread {
        private Tenedor tenedorIzquierdo, tenedorDerecho;
        private int numero;
        private int estado;
        private int COMIENDO = 0;
        private int PENSANDO = 1;
        private int TERMINO = 2;   
        private int x0, y0;

        public Filosofo(Tenedor izq, Tenedor der, int unNumero, int unX, int unY) {
            tenedorIzquierdo = izq;
            tenedorDerecho = der;
            this.numero = unNumero;
            x0 = unX;
            y0 = unY;
            estado = TERMINO;
        }

        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                tenedorIzquierdo.get();
                tenedorDerecho.get();
                
                System.out.println("Filosofo #" + this.numero
                + " come : " + i);
                ponEstado(COMIENDO);
                try {
                sleep(1000+ (int)(Math.random() * 10));
                } catch (InterruptedException e) { }

                tenedorIzquierdo.put();
                tenedorDerecho.put();
                
                System.out.println("Filosofo #" + this.numero
                + " piensa : " + i);
                ponEstado (PENSANDO);
                try {
                sleep(100 +(int)(Math.random() * 1000));
                } catch (InterruptedException e) { }               
           }
            ponEstado(TERMINO);
        }
        
        public void ponEstado(int unEstado) {
            estado = unEstado;
            repaint();
        }
        
        public void dibuja(Graphics g) {
            if(estado == COMIENDO) g.setColor(Color.RED);
            else if(estado == PENSANDO) g.setColor(Color.BLACK);

            if(estado != TERMINO) {
                g.fillOval(x0, y0, 20, 20);
                g.drawString(""+numero, x0+7, y0+15);
            }
        }
    }
    
     private class Tenedor {
       private boolean disponible = true;
       
       public synchronized void get() {
          while (disponible == false) {
             try {
                wait();
             }
             catch (InterruptedException e) {
             }
          }
          disponible = false;
          notify();
       }  
       
       public synchronized void put() {
          while (disponible == true) {
             try {
                wait();
             }
             catch (InterruptedException e) { 
             } 
          }
          disponible = true;
          notify();
       }
    }
     
    private class AreaDibujo extends JPanel {
        public AreaDibujo() {
            this.setBackground(Color.WHITE);
            this.setPreferredSize(new Dimension(300,300));
        }
        
        @Override
        public void paint(Graphics g) {
            super.paint(g);
            for(int i=0; i<5; i++)
                filosofos[i].dibuja(g);
        }
    } 
    
    static public void main(String args[])
    {
        new CenaFilosofos();
    }
}
