Jantar dos Filósofos - Resolução

package jantardosfilosofos;

import javax.swing.JFrame;

/**
 * Pós-Java PGN0060
 *
 * @Monteiro
 */
public class JantarDosFilosofos extends JFrame {

    public JantarDosFilosofos() {
        // Janela
        add(new Grade());

        // Titulo
        setTitle("Jantar dos Filósofos");

        // Operação ao fechar a janela
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        // Tamanho do frame
        setSize(500, 500);

        // Local
        setLocationRelativeTo(null);

        // Visibilidade
        setVisible(true);

        // Bloqueia o redimensionamento
        setResizable(false);

    }

    public static void main(String[] args) {
        new JantarDosFilosofos();
    }

}

package jantardosfilosofos;

/**
 * Pós-Java PGN0060
 * @Monteiro 19/03/2016
 */

public class Filosofo extends Thread {
    // Cria um código privado para o filósofo
    private int ID;

    // Cria padrões de comportamento do filósofo
    final int PENSANDO = 0;
    final int FAMINTO  = 1;
    final int COMENDO  = 2;

    // Método construtor que recebe um nome para a classe e um código de
    // identificação do filósofo
    public Filosofo (String nome, int ID)
    {
        super(nome);
        this.ID = ID;
    }

    // Método para definir que o filósofo está com fome
    public void ComFome ()
    {
        // Seta o estado deste filósofo na classe Grade para FAMINTO
        Grade.estado[this.ID] = 1;
        // Exibe uma mensagem de controle na tela
        System.out.println("O Filósofo " + getName() + " está FAMINTO!");
    }

    // Método para definir que o filósofo está comendo
    public void Come ()
    {
        // Seta o estado deste filósofo na classe Grade para COMENDO
        Grade.estado[this.ID] = 2;
        // Exibe uma mensagem de controle na tela
        System.out.println("O Filósofo " + getName() + " está COMENDO!");

        // Será criado um controle para o filósofo permanecer comendo
        // durante certo período de tempo
        try
        {
            // Fica parado neste estado por 1000 milisegundos
            Thread.sleep(1000L);
        }
        catch (InterruptedException ex)
        {
            // Exibe uma mensagem de controle de erro
            System.out.println("ERROR>" + ex.getMessage());
        }
    }

    // Método para definir que o filósofo está pensando
    public void Pensa ()
    {
        // Seta o estado deste filósofo na classe Grade para PENSANDO
        Grade.estado[this.ID] = 0;
        // Exibe uma mensagem de controle na tela
        System.out.println("O Filósofo " + getName() + " está PENSANDO!");

        // Será criado um controle para o filósofo permanecer pensando
        // durante certo período de tempo
        try
        {
            // Fica parado neste estado por 1000 milisegundos
            Thread.sleep(1000L);
        }
        catch (InterruptedException ex)
        {
            // Exibe uma mensagem de controle de erro
            System.out.println("ERROR>" + ex.getMessage());
        }
    }

    // Método para o filósofo soltar um garfo que ele pegou
    public void LargarGarfo ()
    {
        // Decrementa o semáforo mutex principal da classe, isso permite
        // informar que o atual método está operando na mesa dos filósofos
        Grade.mutex.decrementar();

        // Coloca o filósofo para pensar determinado tempo
        Pensa();

        // Após o filósofo pensar, ele vai informar para os seus vizinhos
        // que podem tentar pegar os garfos que já estão disponíveis
        Grade.filosofo[VizinhoEsquerda()].TentarObterGarfos();
        Grade.filosofo[VizinhoDireita()].TentarObterGarfos();

        // Após operar, volta o semáforo mutex para o estado normal
        // indicando que já realizou todos procedimentos na mesa
        Grade.mutex.incrementar();
    }

    // Método para o filósofo pegar um garfo na mesa
    public void PegarGarfo ()
    {
        // Decrementa o semáforo mutex principal da classe, isso permite
        // informar que o atual método está operando na mesa dos filósofos
        Grade.mutex.decrementar();

        // Deixa o filósofo faminto por determinado tempo
        ComFome();

        // Após o filósofo o período de fome, ele vai verificar com seus
        // vizinhos se ele pode pegar os garfos
        TentarObterGarfos();

        // Após operar, volta o semáforo mutex para o estado normal
        // indicando que já realizou todos procedimentos na mesa
        Grade.mutex.incrementar();
        // Decrementa seu semáforo
        Grade.semaforos[this.ID].decrementar();
    }

    // Método para verificar se o filósofo pode pegar um garfo disposto na mesa
    public void TentarObterGarfos()
    {

        // Verifica se este filósofo está com fome, e se o vizinho da esquerda
        // e da direita não estão comendo
        if (Grade.estado[this.ID] == 1 &&
            Grade.estado[VizinhoEsquerda()] != 2 && 
            Grade.estado[VizinhoDireita()] != 2)
        {
            // Então este filósofo pode comer
            Come();
            // E incrementa o seu semáforo
            Grade.semaforos[this.ID].incrementar();
        }

    }

    // Método de execução da classe, onde o ambiente do filósofo será rodado
    @Override
    public void run ()
    {

        try
        {
            // Coloca o filósofo para pensar
            Pensa();

            // Então realiza uma vida infinita para o filósofo onde inicialmente
            // ele executa os procedimentos de pergar os garfos da mesa, posteriormente
            // ele descansa um pouco, e por fim, ele largar os garfos que ele pegou
            do
            {
                PegarGarfo();
                Thread.sleep(1000L);
                LargarGarfo();
            }
            while (true);
        }
        catch (InterruptedException ex)
        {
            // Exibe uma mensagem de controle de erro
            System.out.println("ERROR>" + ex.getMessage());
            // E da um retorno de cancelamento
            return;
        }

    }

    // Método para obter o filósofo vizinho da direita
    public int VizinhoDireita ()
    {
        // Rationa o valor em 5 posições, ou seja, se o ID deste filósofo acrescentado
        // de um for maior que quatro, passa a ser zero
        return (this.ID + 1) % 5;
    }

    // Método para obter o filósofo vizinho da esquerda
    public int VizinhoEsquerda ()
    {
        if (this.ID == 0)
        {
            // Retorna a ultima posição
            return 4;
        }
        else
        {
            // Rationa o valor em 5 posições, ou seja, se o ID deste filósofo decrescido
            // de um for menor que zero, passa a ser quatro
            return (this.ID - 1) % 5;
        }
    }

}

package jantardosfilosofos;

/**
 *
 * @author aluno
 */
public class Semaforo {
    // Criação de um contador protegido para esta classe
    protected int contador;

    // Método construtor da classe que não recebe nenhum valor
    public Semaforo ()
    {
        this.contador = 0;
    }

    // Método construtor da classe que recebe um valor para setar no
    // contador
    public Semaforo (int valor)
    {
        this.contador = valor;
    }

    // Método de sincronização da classe onde será decrescido o contador
    public synchronized void decrementar ()
    {

        // Enquanto o contador for igual a 0, ele aguarda e trata a exceção
        while (this.contador == 0)
        {
            try
            {
                // Espera uma nova solicitação
                wait();
            }
            catch (InterruptedException ex)
            {
                // Exibe uma mensagem de controle de erro
                System.out.println("ERROR>" + ex.getMessage());
            }
        }

        // Caso tenha saído do while acima, então decrementa o
        // contador da classe
        this.contador--;

    }

    // Método de sincronização da classe onde será incrementado o contador
    public synchronized void incrementar ()
    {
        // Incrementa o contador da classe
        this.contador++;
        // Notifica que a solicitação já foi executada
        notify();
    }

}

package jantardosfilosofos;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Toolkit;
import javax.swing.JPanel;

/**
 *
 * @author aluno
 */

public class Grade extends JPanel implements Runnable{
    
    // Cria padrões de comportamento dos filósofos
    final int PENSANDO = 0;
    final int FAMINTO  = 1;
    final int COMENDO  = 2;

    // Mensagem para cada um dos estados
    String mensagem = "";

    // Thread principal da aplicação
    Thread animador;

    // Criação dos semáforos da aplicação

    // O semáforo mutex que recebe o valor incial 1 para o contador
    // e é o semáforo principal da nossa aplicação
    public static Semaforo mutex = new Semaforo(1);

    // O vetor semáforos são normais e existe um semáforo para cada filósofo
    // que será criado, esses semafóros não recebem valores de inicialização
    // portanto iniciando o contador em 0
    public static Semaforo semaforos[] = new Semaforo[5];

    // Define um vetor para o estado de cada um dos filósofos presentes
    // na aplicação
    public static int estado[] = new int[5];

    // Cria 5 filósofos em um vetor para a aplicação
    static Filosofo filosofo[] = new Filosofo[5];

    // Método construtor da Grade da aplicação
    public Grade ()
    {
        // Define o foco para este JPanel
        setFocusable(true);

        // Define um tamanho para a tela
        setSize(400, 400);
        
        // Seta a cor do fundo
        setBackground(Color.white);
        
        init();
    }

    // Método para inicializar tudo o que é preciso dentro da classe
    public void init ()
    {
        // Inicializa todos estados para zero
        for (int i = 0; i < estado.length; i++)
        {
            estado[i] = 0;
        }

        // Verifica se o Thread de animação é vazio
        if(animador == null)
        {
            // Então cria um novo Thread
            animador = new Thread(this);
            // Inicia sua execução
            animador.start();
        }

        // Define a prioridade principal para este atual Thread
        Thread.currentThread().setPriority(1);

        // Inicializa todos filósofos
        filosofo[0] = new Filosofo("Platao", 0);
        filosofo[1] = new Filosofo("Socrates", 1);
        filosofo[2] = new Filosofo("Aristoteles", 2);
        filosofo[3] = new Filosofo("Tales", 3);
        filosofo[4] = new Filosofo("Sofocles", 4);

        // Inicializa todos semáforos
        semaforos[0] = new Semaforo(0);
        semaforos[1] = new Semaforo(0);
        semaforos[2] = new Semaforo(0);
        semaforos[3] = new Semaforo(0);
        semaforos[4] = new Semaforo(0);

        // Inicia a execução de todos filósofos
        filosofo[0].start();
        filosofo[1].start();
        filosofo[2].start();
        filosofo[3].start();
        filosofo[4].start();
    }

    // Método para desenhar os objetos na tela da aplicação
    @Override
    public void paint(Graphics g)
    {
        super.paint(g);
        
        // Define a cor azul
        g.setColor(Color.blue);
        // Cria um circulo na posição (50,50) do plano cartesiano com tamanho
        // 300x300
        g.drawOval(50, 50, 300, 300);

        // Para cada um dos filósofos será feito um desenho
        for(int i = 0; i < 5; i++)
        {            
            // Define a cor para cara tipo de estado
            if(estado[i] == 0)
            {
                g.setColor(Color.gray);
                mensagem = "PENSANDO";
            }
            if(estado[i] == 1)
            {
                g.setColor(Color.yellow);
                mensagem = "FAMINTO";
            }
            if(estado[i] == 2)
            {
                g.setColor(Color.green);
                mensagem = "COMENDO";
            }
            
            // Desenha o filósofo, sua carinha e seu nome na tela
            // Define os planos (x,y) e posteriormente o tamanho do objeto a ser desenhado
            g.fillOval((int)(200D - 100D * Math.cos(1.2566370614359172D * (double)i)) - 15, (int)(200D - 100D * Math.sin(1.2566370614359172D * (double)i)) - 15, 30, 30);
            g.setColor(Color.black);
            g.drawLine((int)(200D - 100D * Math.cos(1.2566370614359172D * (double)i)) - 5, (int)(200D - 100D * Math.sin(1.2566370614359172D * (double)i)) + 5, (int)(200D - 100D * Math.cos(1.2566370614359172D * (double)i)) + 5, (int)(200D - 100D * Math.sin(1.2566370614359172D * (double)i)) + 5);
            g.drawLine((int)(200D - 100D * Math.cos(1.2566370614359172D * (double)i)) - 2, (int)(200D - 100D * Math.sin(1.2566370614359172D * (double)i)) - 3, (int)(200D - 100D * Math.cos(1.2566370614359172D * (double)i)) + 2, (int)(200D - 100D * Math.sin(1.2566370614359172D * (double)i)));
            g.drawLine((int)(200D - 100D * Math.cos(1.2566370614359172D * (double)i)) - 2, (int)(200D - 100D * Math.sin(1.2566370614359172D * (double)i)), (int)(200D - 100D * Math.cos(1.2566370614359172D * (double)i)) + 2, (int)(200D - 100D * Math.sin(1.2566370614359172D * (double)i)));
            g.drawLine((int)(200D - 100D * Math.cos(1.2566370614359172D * (double)i)) - 8, (int)(200D - 100D * Math.sin(1.2566370614359172D * (double)i)) - 8, (int)(200D - 100D * Math.cos(1.2566370614359172D * (double)i)) - 3, (int)(200D - 100D * Math.sin(1.2566370614359172D * (double)i)) - 8);
            g.drawLine((int)(200D - 100D * Math.cos(1.2566370614359172D * (double)i)) + 3, (int)(200D - 100D * Math.sin(1.2566370614359172D * (double)i)) - 8, (int)(200D - 100D * Math.cos(1.2566370614359172D * (double)i)) + 8, (int)(200D - 100D * Math.sin(1.2566370614359172D * (double)i)) - 8);
            g.drawString(filosofo[i].getName(), (int)(200D - 100D * Math.cos(1.2566370614359172D * (double)i)) - 15, (int)(200D - 100D * Math.sin(1.2566370614359172D * (double)i)) + 25);
            g.drawString(mensagem, (int)(200D - 100D * Math.cos(1.2566370614359172D * (double)i)) - 15, (int)(200D - 100D * Math.sin(1.2566370614359172D * (double)i)) + 40);
        }

        // ATIVA A SINCRONIA
        Toolkit.getDefaultToolkit().sync();
        // PAUSA
        g.dispose();

    }

    // Método de execução da classe, onde o ambiente será rodado
    public void run ()
    {        
        // Uma execução infinita
        do
        {
            // Redesenha a tela
            repaint();

            // Dorme durante um tempo para redesenhar novamente
            try
            {
                Thread.sleep(1000L);
            }
            catch (InterruptedException ex)
            {
                // Exibe uma mensagem de controle de erro
                System.out.println("ERROR>" + ex.getMessage());
            }
        }
        while (true);
    }

}

Comentários

Postagens mais visitadas deste blog

Classes(abstratas e concretas), Objetos, Métodos, Construtores, Vetor de Objetos e trabalhar o conceito de interface.

Questão Comentada - Prof Nelson Lage

GST0070 - Comércio Eletrônico - Aula 5