Professional Documents
Culture Documents
Disciplina
Sistemas Operacionais
Jacques Philippe Sauv Jos Maria Rodrigues Santos Jnior Threads em Java
O que Thread ?..............................................................................................................................................................................3 Definio de Processo..................................................................................................................................................................3 Definio de Thread.....................................................................................................................................................................3 Paralelismo x Concorrncia.........................................................................................................................................................4 Thread em Java................................................................................................................................................................................4 Criando Threads em Java.............................................................................................................................................................6 Implementando o Comportamento de uma Thread..................................................................................................................6 Criando uma subclasse de Thread............................................................................................................................................6 Exemplo de criao de threads estendendo a classe Thread................................................................................................6 Implementando a Interface Runnable......................................................................................................................................7 Exemplo de thread implementando a interface Runnable...................................................................................................7 Escolhendo entre os dois mtodos de criao de threads........................................................................................................7 Um exemplo mais interessante de threads em Java.....................................................................................................................8 Resultado da Execuo Corrida de Sapos.............................................................................................................................9 O ciclo de vida de uma Thread..................................................................................................................................................10 Criando Threads.....................................................................................................................................................................11 Iniciando Threads...................................................................................................................................................................11 Fazendo Thread Esperar.........................................................................................................................................................11 Finalizando Threads...............................................................................................................................................................11 Verificando se Threads esto Executando/Pronta/Esperando ou Novas/Mortas....................................................................11 Threads Daemon........................................................................................................................................................................12 Escalonamento de Threads.........................................................................................................................................................12 Exemplo de aplicao usando threads com diferentes prioridades........................................................................................13 Sincronizando Threads (Concorrncia).....................................................................................................................................14 Implementando Excluso Mtua de Regies Crticas...........................................................................................................14 Comunicao Entre Threads..................................................................................................................................................14 Evitando Starvation e Deadlock.............................................................................................................................................15 Agrupando Threads....................................................................................................................................................................16 O Grupo Padro de Threads...................................................................................................................................................16 Criando Grupos de Threads e Inserindo Threads...................................................................................................................16 Operaes sobre Grupos de Threads......................................................................................................................................16 O Exemplo Produtor/Consumidor ou Buffer Limitado ............................................................................................................17 Resultado da Execuo Produtor/Consumidor...................................................................................................................23 O Exemplo do Jantar dos Filsofos Glutes..............................................................................................................................24 Resultado da Execuo Jantar do Filsofos Glutes..........................................................................................................29 Bibliografia....................................................................................................................................................................................30 Fontes de Pesquisa.........................................................................................................................................................................30
Threads em Java
O que Thread ?
O conceito de thread est intimamente ligado ao conceito de processo, assim fundamental entender o que so processos, como eles so representados e colocados em execuo pelo Sistema Operacional, para em seguida entender as threads. Dessa forma segue uma breve definio de Processo e posteriormente a de Thread.
Definio de Processo
Um processo basicamente um programa em execuo, sendo constitudo do cdigo executvel, dos dados referentes ao cdigo, da pilha de execuo, do valor do contador de programa (registrador PC), do valor do apontador do apontador de pilha (registrador SP), dos valores dos demais registradores do hardware, alm de um conjunto de outras informaes necessrias execuo dos programas. Tanenbaum Podemos resumir a definio de processo dizendo que o mesmo formado pelo seu espao de endereamento lgico e pela sua entrada na tabela de processos do Sistema Operacional. Assim um processo pode ser visto como uma unidade de processamento passvel de ser executado em um computador e essas informaes sobre processos so necessrias para permitir que vrios processos possam compartilhar o mesmo processador com o objetivo de simular paralelismo na execuo de tais processos atravs da tcnica de escalonamento, ou seja, os processos se revezam (o sistema operacional responsvel por esse revezamento) no uso do processador e para permitir esse revezamento ser necessrio salvar o contexto do processo que vai ser retirado do processador para que futuramente o mesmo possa continuar sua execuo.
Definio de Thread
Thread, ou processo leve, a unidade bsica de utilizao da CPU, consistindo de : contador de programa, conjunto de registradores e uma pilha de execuo. Thread so estruturas de execuo pertencentes a um processo e assim compartilham os segmentos de cdigo e dados e os recursos alocados ao sistema operacional pelo processo. O conjunto de threads de um processo chamado de Task e um processo tradicional possui uma Task com apenas uma thread. Silberschatz O conceito de thread foi criado com dois objetivos principais : Facilidade de comunicao entre unidades de execuo e reduo do esforo para manuteno dessas unidades. Isso foi conseguido atravs da criao dessas unidades dentro de processos, fazendo com que todo o esforo para criao de um processo, manuteno do Espao de endereamento lgico e PCB, fosse aproveitado por vrias unidades processveis, conseguindo tambm facilidade na comunicao entre essas unidades. Dessa forma o escalonamento de threads de um mesmo processo ser facilitado pois a troca de contexto entre as threads exigir um esforo bem menor. Sendo que ainda assim, ocorrer o escalonamento de processos, pois outros processos podero estar sendo executado paralelamente ao processo que possui as threads. Podemos concluir ento que a real vantagem obtida no escalonamento de threads de um mesmo processo e na facilidade de comunicao entre essas threads.
Paralelismo x Concorrncia
Threads podem executar suas funes de forma paralela ou concorrente, onde quando as threads so paralelas elas desempenham o seus papeis independente uma das outras. J na execuo concorrente, as threads atuam sobre objetos compartilhados de forma simbitica necessitando de sincronismo no acesso a esses objetos, assim deve ser garantido o direito de atomicidade e excluso mtua nas operaes das threads sobre objetos compartilhados.
Thread em Java
Todo programador est familiarizado com a programao sequencial, pois sem dvida at o presente momento esta a forma de programao mais comum. Programas do tipo Hello World, ou que ordenam uma lista de nome, ou que gera e imprime uma lista de nmeros primos, etc so programas tipicamente sequenciais, onde cada um possui : seu incio, sequncia de execuo e fim e em qualquer momento da sua execuo estes programas possuem apenas um ponto de execuo. Uma thread similar ao programas sequenciais, pois possui um incio, sequncia de execuo e um fim e em qualquer momento uma thread possui um nico ponto de execuo. Contudo, uma thread no um programa, ela no pode ser executada sozinha e sim inserida no contexto de uma aplicao, onde essa aplicao sim, possuir vrios pontos de execues distintos, cada um representado por uma thread. A figura abaixo descreve esse mecanismo de funcionamento da thread dentro de um programa em execuo.
Texto
Programa
- Processo
Informaes para Gerncia do Processo Process Control Block Informaes (PCB) para Gerncia de Memria Informaes para Gerncia de Arquivos
No h nada de novo nesse conceito de processo com uma nica thread, pois o mesmo idntico ao conceito tradicional de processo. O grande benefcio no uso de thread quando temos vrias thread num Informaes mesmo processo sendo executadas simultaneamente e podendo realizar tarefas diferentes. A figura abaixo Segmento de para Gerncia representa um processo com mltiplas threads (Programao Multi-Thread.) Texto do Processo
Texto Texto Pilha de Pilha Thread Thread Programa em Execuo - Processo de Execuo Execuo Definio : Com mltiplas theads um programa possui mltiplos pontos de Registradores Registradores Segmento de
...
Process Control Block Informaes (PCB) para Gerncia execuo de Memria Informaes
Pilha Dessa forma podemos perceber facilmente que aplicaes multithreads podem realizar tarefas para Gerncia de Arquivos distintas ao mesmo tempo, dando idia de paralelismo. Veja um exemplo do navegador web HotJava, o qual consegue carregar e executar applets, executar uma animao, tocar um som, exibir diversas figuras, permitir rolagem da tela, carregar uma nova pgina, etc e para o usurio todas essas atividades so simultneas, mesmo possuindo um nicoProcesso com mltiplas Threads por que dentro da aplicao do processador. Isso possvel, navegador HotJava vrias threads foram executadas, provavelmente, uma para cada tarefa a ser realizada.
Alguns autores tratam threads como processos leves. Uma thread similar a um processo no sentido que ambos representam um nico fluxo de controle de execuo, sendo considerada um processo leve por ser executada dentro do contexto de um processo e usufruir dos recursos alocados pelo processo. Cada thread necessita possuir apenas as informaes (contador de programa e pilha de execuo) necessrias a sua execuo, compartilhando todo o contexto de execuo do processo com todas a demais threads do mesmo processo. A linguagem Java possui apenas alguns mecanismos e classes desenhadas com a finalidade de permitir a programao Multi-Thread, o que torna extremamente fcil implementar aplicaes MultiThreads, sendo esses :
A classe java.lang.Thread utilizada para criar, iniciar e controlar Threads; As palavras reservadas synchronized e volatile usadas para controlar a execuo de cdigo em objetos compartilhados por mltiplas threads, permitindo excluso mtua entre estas; Os mtodos wait, notify and notifyAll definidos em java.lang.Object usados para coordenar as atividades das threads, permitindo comunicao entre estas.
/** Construtor da classe. Parmtros : Nome do Sapo e Distncia da Corrida */ public SapoCorrendoThread (String nome, int distanciaTotalCorrida) { /* chamando o construtor de Thread passando o nome do sapo como parmetro */ super(nome); this.distanciaTotalCorrida = distanciaTotalCorrida; this.nome = nome; } /** Imprime o ltimo pulo do sapo e a distncia percorrida */ public void sapoImprimindoSituacao () { System.out.println("O " + nome + " pulou " + pulo + "cm \t e j percorreu " + distanciaCorrida + "cm"); } /** Faz o sapo pular */ public void sapoPulando() { pulos++; pulo = (int) (Math.random() * PULO_MAXIMO); distanciaCorrida += pulo; if (distanciaCorrida > distanciaTotalCorrida) { distanciaCorrida = distanciaTotalCorrida; } } /** Representando o descanso do sapo */ public void sapoDescansando () { /* Mtodo que passa vez a outras threads */ yield(); } /** Imprime a colocao do sapo ao final da corrida */ public void colocacaoSapo () { colocacao++; System.out.println(nome + " foi o " + colocacao + " colocado com " + pulos + " pulos"); } /** Mtodo run da thread Corrida de Sapos */ public void run () { while (distanciaCorrida < distanciaTotalCorrida) { sapoPulando(); sapoImprimindoSituacao(); sapoDescansando(); } colocacaoSapo(); } }
200cm
Escalonador yield()
Estados de Threads
new Thread()
Esperando
Nova
Executando
Mort a
10
Criando Threads
A criao de uma thread feita atravs da chamado ao seu construtor colocando a thread no estado Nova, o qual representa uma thread vazia, ou seja, nenhum recurso do sistema foi alocado para ela ainda. Quando uma thread est nesse estado a nica operao que pode ser realizada a inicializao dessa thread atravs do mtodo start(), se qualquer outro mtodo for chamado com a thread no estado Nova ir acontecer uma exceo (IllegalThreadStateException), assim como, quando qualquer mtodo for chamado e sua ao no for condizente com o estado atual da thread.
Iniciando Threads
A inicializao de uma thread feita atravs do mtodo start() e nesse momento os recursos necessrios para execuo da mesma so alocados, tais como recursos para execuo, escalonamento e chamada do mtodo run da thread. Aps a chamada ao mtodo start a thread est pronta para ser executada e ser assim que for possvel, at l ficar no estado Pronta. Essa mudana de estado (Pronta/Executando) ser feito pelo escalonador do Sistema de Execuo Java. O importante saber que a thread est pronta para executar e a mesma ser executada, mais cedo ou mais tarde de acordo com os critrios, algoritmo, de escalonamento do Sistema de Execuo Java.
Se a thread solicitou dormir por determinado intervalo de tempo (sleep), assim que este intervalo de tempo for decorrido; Se a thread solicitou esperar por determinado evento (wait), assim que esse evento ocorrer (outra thread chamar notify ou notifyAll); Se a thread realizou solicitao de I/O, assim que essa solicitao for atendida.
Finalizando Threads
Uma Thread finalizada quando acabar a execuo do seu mtodo run, e ento ela vai para o estado Morta, onde o Sistema de Execuo Java poder liberar seus recursos e elimin-la .
11
Threads Daemon
So threads que rodam em background e realizam tarefas de limpeza ou manuteno, as quais devem rodar enquanto a aplicao estiver em execuo, as threads daemons somente morrerem quando a aplicao for encerrada. Sendo que o Sistema de Execuo Java identifica que uma aplicao acabou quando todas as suas threads esto morta, assim para que seja possvel que uma aplicao seja encerrada ainda possuindo threads, tais threads devem ser daemon. Em outras palavras, o Sistema de Execuo Java ir terminar uma aplicao quando todas as suas threads no daemon morrerem. Threads daemons so denominadas de Threads de Servio e as no daemon so denominadas de Threads de Usurio. Os mtodos para manipulao de threads daemon so: public final void setDaemon(boolean) public final boolean isDaemon() Torna ou no uma thread daemon Verifica se uma thread daemon
Escalonamento de Threads
O escalonamento fundamental quando possvel a execuo paralela de threads, pois, certamente existiro mais threads a serem executadas que processadores, assim a execuo paralela de threads simulada atravs de mecanismos do escalonamento dessas threads, onde os processadores disponveis so alternados pelas diversas threads em execuo. O mecanismo de escalonamento utilizado pelo Sistema de Execuo Java bastante simples e determinstico, e utiliza um algoritmo conhecido como Escalonamento com Prioridades Fixas, o qual escalona threads baseado na sua prioridade. As threads escalonveis so aquelas que esto nos estados Executando ou Pronta, para isso toda thread possui uma prioridade, a qual pode ser um valor inteiro no intervalo [MIN_PRIORITY ... MAX_PRIORITY], (estas so constantes definidas na classe Thread), e quanto maior o valor do inteiro maior a prioridade da thread. Cada thread Nova recebe a mesma prioridade da thread que a criou e a prioridade de uma thread pode ser alterada atravs do mtodo setPriority(int priority). O algoritmo de escalonamento com Prioridades Fixas utilizado pela Sistema de Execuo Java funcionada da seguinte forma : 1. Quando vrias threads estiverem Prontas, aquela que tiver a maior prioridade ser executada. 2. Quando existir vrias threads com prioridades iguais, as mesmas sero escalonadas segundo o algoritmo Round-Robin de escalonamento. 3. Uma thread ser executada at que : uma outra thread de maior prioridade fique Pronta; acontecer um dos eventos que a faa ir para o estado Esperando; o mtodo run acabar; ou em sistema que possuam fatias de tempo a sua fatia de tempo se esgotar. 4. Threads com prioridades mais baixas tero direito garantido de serem executadas para que situaes de starvation no ocorram.
12
13
14
Observao : Esses mtodos devem ser usados na implementao das operaes dos objetos sincronizados, ou seja, nos mtodos synchronized dos objetos sincronizados. Pois s faz sentido uma thread notificar ou esperar por outra em objetos sincronizados e o Sistema de Execuo Java tem mecanismos para saber qual thread ir esperar ou receber a notificao, pois somente uma thread por vez pode estar executando um mtodo sincronizado de um objeto compartilhado.
15
Agrupando Threads
Toda thread Java membro de um grupo . Grupo de threads um mecanismo para agrupar vrias threads em um nico objeto e permitir realizar operaes sobre todas elas mais facilmente. O Sistema de Execuo Java coloca threads em grupos no momento da sua criao. Quando uma thread criada a mesma colocada num grupo padro pelo Sistema de Execuo Java ou o grupo pode ser especificado pelo programador. Uma vez criada, a thread membro permanente do seu grupo e a mesma no pode ser movida para outro grupo.
16
17
/** * @author Jos Maria Rodrigues Santos Junior * zemaria@unitnet.com.br / http://www.unit.br/zemaria * * Classe de thread Produtora */ class ProdutorThread extends Thread { /* objeto para referenciar o buffer */ BufferLimitado buffer; /* quantidade de itens a serem produzidos */ int quantItens; /** * Construtor * @param threadGroup Grupo da thread * @param nomeThread Nome da thread * @param buffer buffer a ser utilizado * @param quantItens quantidade de itens a serem produzidos */ public ProdutorThread (ThreadGroup threadGroup,String nomeThread, BufferLimitado buffer, int quantItens) { super(threadGroup, nomeThread); this.buffer = buffer; this.quantItens = quantItens; } /* * Mtodo run da thread, o qual contm o ser comportamento */ public void run () { for (int i = 1; i <= quantItens; i++) { /* Gera um novo item aleatoriamente */ int novoItem = (int) (Math.random() * 10); /* Insere o novo item no buffer */ buffer.insere(novoItem); /* dorme pelo intervalo de tempo aleatrio [0 ... 100]mseg */ int tempo = (int) (Math.random() * 1000); dorme(tempo); } } private void dorme(int tempo) { try { sleep(tempo); } catch (InterruptedException e) { System.out.println(e.getMessage()); } } }
18
/** * @author Jos Maria Rodrigues Santos Junior * zemaria@unitnet.com.br / http://www.unit.br/zemaria * * Classe de thread consumidora */ class ConsumidorThread extends Thread { /* objeto para referenciar o buffer */ BufferLimitado buffer; /* quantidade de itens a serem consumidos */ int quantItens; /** * Construtor * @param threadGroup Grupo da thread * @param nomeThread Nome da thread * @param buffer buffer a ser utilizado * @param quantItens quantidade de itens a serem consumidos */ public ConsumidorThread (ThreadGroup threadGroup, String nomeThread, BufferLimitado buffer, int quantItens) { super(threadGroup, nomeThread); this.buffer = buffer; this.quantItens = quantItens; } /* * Mtodo run da thread, o qual contm o ser comportamento */ public void run () { for (int i = 1; i <= quantItens; i++) { /* Retita um elemtno do buffer */ buffer.retira(); /* dorme pelo intervalo de tempo aleatrio [0 ... 100]mseg */ int tempo = (int) (Math.random() * 1000); dorme(tempo); } } private void dorme(int tempo) { try { sleep(tempo); } catch (InterruptedException e) { System.out.println(e.getMessage()); } } }
19
/** * @author Jos Maria Rodrigues Santos Junior * zemaria@unitnet.com.br / http://www.unit.br/zemaria * * Classe representando o buffer limitado a ser compartilhado pelas threads * Produtoras e Consumidoras */ class BufferLimitado { /* tamano do buffer */ private final static int TAMANHO = 5; /* buffer */ private int[] buffer = new int[TAMANHO]; /* posio para inserco de novo item (in) */ private int posicaoInsere = 0; /* posio para remoo do item (out) */ private int posicaoRetira = 0; /* quantidades de itens no buffer */ private int quantItens = 0; /* Construtor */ public BufferLimitado () { } /** * Insere um novo item no buffer * @param novoItem item a ser inserido no buffer */ synchronized public void insere (int novoItem) { /* enquanto o buffer estiver cheio a thread deve esperar */ while (quantItens == TAMANHO) { try { wait(); } catch (InterruptedException e){ System.out.println("Erro de Estado da Thread " + e.getMessage()); } } /* colocando novo item no buffer */ buffer[posicaoInsere] = novoItem; /* exibindo informes sobre a insero do novo item */ System.out.print("Inserindo " + novoItem + "\tna posio " + posicaoInsere + "\t"); /* atualizando a posio de insero */ posicaoInsere = proximaPosicao(posicaoInsere); /* incrementando a quantidade de itens no buffer */ quantItens++; /* imprimindo o buffer */ imprime(); /* caso o buffer estivesse vazio, acordar as threads consumidoras */ if (quantItens == 1) { notifyAll(); } }
20
/** * Retira um item do buffer * @return Item retirado do buffer */ synchronized public int retira () { int itemRetirado; // item retirado /* enquanto o buffer estiver vazio a thread deve esperar */ while (quantItens == 0) { try { wait(); } catch (InterruptedException e){ System.out.println("Erro de Estado da Thread " + e.getMessage()); } } /* armazendo o item a ser retirado */ itemRetirado = buffer[posicaoRetira]; /* atualizando a quantidade de itens */ quantItens--; /* exibindo informaes sobre a retirado do item do buffer */ System.out.print("Retirando " + itemRetirado + "\tda posio " + posicaoRetira + "\t"); /* atualizando a posio de retirado */ posicaoRetira = proximaPosicao(posicaoRetira); /* imprimindo o buffer */ imprime(); /* caso o buffer estivesse cheio, acordar as threads produtoras */ if (quantItens == TAMANHO - 1) { notifyAll(); } /* retorna o item retirado */ return itemRetirado; } /** * Obtem a prxima posio no buffer * @param posicaoAtual a atual posicao no buffer * @return a prmixa posio no buffer */ private int proximaPosicao (int posicaoAtual) { /* obtem a nova posio */ int novaPosicao = ++posicaoAtual; /* caso ultrapasse o tamanho do buffer,ir para o 1 posio (0) */ if (novaPosicao > TAMANHO - 1) { novaPosicao = 0; } return novaPosicao; } /** * Obtem a posio anterior no buffer * @param posicaoAtual a atual posicao no buffer * @return a posio anterior no buffer */ private int posicaoAnterior (int posicaoAtual) { /* obtem a nova posio */ int novaPosicao = --posicaoAtual; /* caso seja menor que a posio inicial, ir para a ltima posio */ if (novaPosicao < 0) { novaPosicao = TAMANHO-1; } return novaPosicao; }
21
/* * Imprime o buffer */ synchronized private void imprime () { /* posio inicial da impresso */ int inicio = posicaoRetira; /* posio final da impresso */ int fim = posicaoAnterior(posicaoInsere); /* posio impressa */ int i = inicio; /* quantidade de itens impressos */ int quantItensImpressos = 0; System.out.print("\tBuffer[" + quantItens + "] \t= "); while (quantItensImpressos < quantItens) { System.out.print(buffer[i] + " "); i = proximaPosicao(i); quantItensImpressos++; } System.out.println(); } }
22
6 6 5 5 5 5 3 3 2 2 6 3 3 2 1 1 1 1 5 5 8 8 6 6 1 1 5 5 9 9 7 9 7 7 3 3 3 6 6 9 9 9 8
5 3 3 3 2 2 6 6 3 2 2 1 5 5 5 8 8 6 6 1 1 5 5 9 9 7 7 9 7 3 6 6 9 9 8 8 8 2 9 8 2 2 2 2 2 2 6 6 6 3 3 3 2 2 1
8 8 6 6 1 1 5 5 9 9 7 7 9 9 7
6 1 5 9 7 9 7
. . .
23
24
/** * Classe para representar os filosofos * * @author Jos Maria Rodrigues Santos Junior * zemaria@unitnet.com.br * http://www.unit.br/zemaria */ class Filosofo extends Thread { /* Tempo mximo (em milesegundos) que o filsofo vai comer ou pensar */ final static int TEMPO_MAXIMO = 100; /* Referncia mesa de jantar */ MesaDeJantar mesa; /* Filsofo na mesa [0,1,2,3,4] */ int filosofo; public Filosofo (String nomeThread, MesaDeJantar mesa, int filosofo) { /* construtor da classe pai */ super(nomeThread); this.mesa = mesa; this.filosofo = filosofo; } public void run () { int tempo = 0; /* Lao representando a vida de um filsofo : pensar e comer */ while (true) { /* sorteando o tempo pelo qual o filsofo vai pensar */ tempo = (int) (Math.random() * TEMPO_MAXIMO); /* filsofo pensando */ pensar(tempo); /* filsofo pegando garfos */ pegarGarfos(); /* sorteando o tempo pelo qual o filsofo vai comer */ tempo = (int) (Math.random() * TEMPO_MAXIMO); /* filsofo comendo */ comer(tempo); /* filsofo devolvendo garfos */ devolverGarfos(); } } /* simula o filsofo pensando */ private void pensar (int tempo) { try { /* filsofo dorme de tempo milisegundos */ sleep(tempo); } catch (InterruptedException e){ System.out.println("Filfoso pensou demais, morreu"); } } /* simula o filsofo comendo */ private void comer (int tempo) { try { sleep(tempo); } catch (InterruptedException e){ System.out.println("Filfoso comeu demais, morreu"); } } /* pega os garfos */ private void pegarGarfos() { mesa.pegandoGarfos(filosofo); } /* devolve os garfos */ private void devolverGarfos() { mesa.devolvendoGarfos(filosofo); } }
25
/** * Classe para representar a mesa de jantar, talheres * e estados dos fislsofos * * @author Jos Maria Rodrigues Santos Junior * zemaria@unitnet.com.br * http://www.unit.br/zemaria */ class MesaDeJantar { /* filsofo pensando */ final static int PENSANDO = 1; /* filsofo comendo */ final static int COMENDO = 2; /* filsofo com fome */ final static int COM_FOME = 3; /* Quantidade de filsofos */ final static int QUANT_FILOSOFOS = 5; /* Nmero do primeiro filsofo */ final static int PRIMEIRO_FILOSOFO = 0; /* Nmero do ltimo filsofo */ final static int ULTIMO_FILOSOFO = QUANT_FILOSOFOS - 1; /* array[0...QUANT_FILOSOFOS - 1] representando os garfos na mesa : * true = garfo na mesa; false = garfo com filsofo */ boolean[] garfos = new boolean[QUANT_FILOSOFOS]; /* array [0...QUANT_FILOSOFOS - 1] representando o estado de cada um dos filsofos */ int[] filosofos = new int[QUANT_FILOSOFOS]; /* Quantas vezes cada filsofo tentou comer e no conseguiu, * serve para identificar situaes de Starvation */ int[] tentativasParaComer = new int[QUANT_FILOSOFOS]; /* Construtor */ public MesaDeJantar() { /* Preenchendo os vetores de Garfos e filsofos mesa */ for (int i = 0; i < 5; i++) { /* Todos os garfos esto na mesa */ garfos[i] = true; /* Todos os filsofos sentam mesa pensando */ filosofos[i] = PENSANDO; /* Nenhum filsofo tentou comer ainda */ tentativasParaComer[i] = 0; } } /* filosofo pegando os garfos */ synchronized void pegandoGarfos (int filosofo) { /* filsofo com fome */ filosofos[filosofo] = COM_FOME; /* Deve esperar enquanto algum filsofo vizinho estive comendo */ while (filosofos[aEsquerda(filosofo)] == COMENDO || filosofos[aDireita(filosofo)] == COMENDO) { try { /* Filsofo tentou comer e no conseguiu */ tentativasParaComer[filosofo]++; /* colocando o filosofo para esperar */ wait(); } catch (InterruptedException e) { System.out.println("Filsofo morreu de fome"); } } /* Filsofo conseguiu comer */ tentativasParaComer[filosofo] = 0; /* retirando os garfos esquerdo e direito da mesa */ garfos[garfoEsquerdo(filosofo)] = false; garfos[garfoDireito(filosofo)] = false; /* Filsofo comendo */
26
filosofos[filosofo] = COMENDO; imprimeEstadosFilosofos(); imprimeGarfos(); imprimeTentativasParaComer(); } /* Filosofo devolvendo os garfos */ synchronized void devolvendoGarfos (int filosofo) { /* Devolvendo os garfos esquerdo e direito da mesa */ garfos[garfoEsquerdo(filosofo)] = true; garfos[garfoDireito(filosofo)] = true; /* Verificando se h algum filsofo vizinho com fome */ if (filosofos[aEsquerda(filosofo)] == COM_FOME || filosofos[aDireita(filosofo)] == COM_FOME) { /* Notifica (acorda) os vizinhos com fome */ notifyAll(); } /* Filsofo pensando */ filosofos[filosofo] = PENSANDO; imprimeEstadosFilosofos(); imprimeGarfos(); imprimeTentativasParaComer(); } /* Retorna o nmero do filsofo a direita */ private int aDireita (int filosofo) { int direito; /* Caso seja o filsofo n5, a sua direita est o filsofo n1 */ if (filosofo == ULTIMO_FILOSOFO) { direito = PRIMEIRO_FILOSOFO; } else { /* Caso contrrio */ direito = filosofo + 1; } return direito; } /* Retorna o nmero do filsofo a esquerda */ private int aEsquerda (int filosofo) { int esquerdo; /* Caso seja o primeiro filsofo a sua esquerda est o ltimo */ if (filosofo == PRIMEIRO_FILOSOFO) { esquerdo = ULTIMO_FILOSOFO; } else { esquerdo = filosofo - 1; } return esquerdo; } /** Retorna o nmero do garfo a esquerda do filsofo */ private int garfoEsquerdo (int filosofo) { /* O filsofo 1 possui o garfo 1 a sua esquerda e assim por diante */ int garfoEsquerdo = filosofo; return garfoEsquerdo; } /** Retorna o nmero do garfo a direita do filsofo */ private int garfoDireito (int filosofo) { int garfoDireito; /* O ltimo filsofo possui o garfo 0 a sua direita*/ if (filosofo == ULTIMO_FILOSOFO) { garfoDireito = 0; } else { garfoDireito = filosofo + 1; } return garfoDireito; }
27
/* Imprimindo os estados dos filsofos */ private void imprimeEstadosFilosofos () { String texto = "*"; System.out.print("Filsofos = [ "); for (int i = 0; i < QUANT_FILOSOFOS; i++) { switch (filosofos[i]) { case PENSANDO : texto = "PENSANDO"; break; case COM_FOME : texto = "COM_FOME"; break; case COMENDO : texto = "COMENDO"; break; } System.out.print(texto + " "); } System.out.println("]"); } /* Imprimindo os que esto na mesa */ private void imprimeGarfos () { String garfo = "*"; System.out.print("Garfos = [ "); for (int i = 0; i < QUANT_FILOSOFOS; i++) { if (garfos[i]) { garfo = "LIVRE"; } else { garfo = "OCUPADO"; } System.out.print(garfo + " "); } System.out.println("]"); } /* Imprimindo as tentativas de comer dos dos filsofos */ private void imprimeTentativasParaComer () { System.out.print("Tentou comer = [ "); for (int i = 0; i < QUANT_FILOSOFOS; i++) { System.out.print(filosofos[i] + " "); } System.out.println("]"); } }
28
29
Bibliografia
LEA, DOUG. Concurrent Programming in Java - Design Principles and Patterns. The Java Series, Sun Microsystems, 1996.
Fontes de Pesquisa
http://web2.java.sun.com/docs/books/tutorial/essential/threads/index.html http://matter.ccet.umc.br/~paulo/homepagejava/threads.html http://www.inf.unisinos.tche.br/~chris/Paradigma.html#Concorrente http://www.di.ufpe.br/~java/curso/aula7/threads.htm http://www.ime.usp.br/~gubi/local/mac431/index.html http://www.ucs.tche.br/so/javaos/index.htm http://www.javaworld.com/javaworld/jw-04-1996/jw-04-threads.html http://www.eng.uiowa.edu/~skaliann/books/jthreads/index.htm http://java.sun.com/docs/books/vmspec/index.html http://www.javaworld.com/javaworld/jw-09-1998/jw-09-threads.html
30