praticando concorrência em java! _ marcos brizeno
TRANSCRIPT
-
8/18/2019 Praticando Concorrência Em Java! _ Marcos Brizeno
1/9
Marcos Brizeno
setembro 23, 2011
Pr aticando concorrência em J ava!
Neste post vamos mostrar um exemplo prático de programação com concorrência em Java explorando as ferramentas da linguagem
E no começo haviam os monitores
Para começar vamos falar sobre uma estrutura básica na programação concorrente: o monitor.
Segundo [1] monitor é uma técnica utilizada para sincronizar tarefas que compartilham um recurso. ou seja, o monitor oferece umainterface para permitir a manipulação de um recurso compartilhado. Para tanto utiliza uma trava de exclusão mútua, que consiste devariáveis de controle e regras para liberar ou travar o recurso.
Skip to navigation
https://brizeno.wordpress.com/2011/09/23/praticando-concorrencia-em-java/http://-/?-https://brizeno.wordpress.com/2011/09/23/praticando-concorrencia-em-java/https://brizeno.wordpress.com/2011/09/23/praticando-concorrencia-em-java/
-
8/18/2019 Praticando Concorrência Em Java! _ Marcos Brizeno
2/9
De maneira prática, o monitor basicamente é uma classe que controla o recurso, assim quando for preciso requisitá‑lo devemos envipedido para ela.
Produtor/Consumidor
Para exemplificar vamos analisar o problema do Produtor e Consumidor. Segundo [2]:
Uma ou mais thread de produtores criam um produto e colocam em um buffer. Uma ou mais thread de consumidores consomem oproduto colocado no buffer. O produtor precisa esperar o buffer ficar livre para produzir o produto e o cliente precisa esperar o buffeficar preenchido para consumir o produto.
A tarefa do problema é sincronizar o acesso ao recurso, no caso a pilha, para que produtores saibam quando podem produzir econsumidores saibam quando podem consumir. Vamos então para a parte prática!
Primeiro vamos criar a classe do Consumidor:
123456789
1011121314151617
public class Consumidor extends Thread { private int idConsumidor; private Buffer pilha; private int totalConsumir;
public Consumidor( int id, Buffer p, int totalConsumir) { idConsumidor = id; pilha = p; this .totalConsumir = totalConsumir; }
public void run() { for ( int i = 0; i < totalConsumir; i++) { pilha.get(idConsumidor); } System.out.println( "Consumidor #" + idConsumidor + " concluido!" ); }
-
8/18/2019 Praticando Concorrência Em Java! _ Marcos Brizeno
3/9
Essa classe é derivada da clase Thread, ou seja, cada cliente vai funcionar em um thread diferente. Os dados que utilizamos são umidentificador (idConsumidor), uma referência para um Buffer e um contador (totalConsumir) que vai indicar quanto deve ser consumpelo consumidor.
O método run() é chamado quando a thread for iniciada, ou seja, é nele que devemos definir o nosso cliente de fato. Definimos entãpara executar as chamadas que consomem o recurso do buffer.
Vamos então definir a classe Produtor:
De maneira semelhante ao Consumidor, o produtor possui um identificador, uma referência para um buffer e um total de produtos aserem produzidos. Note que essa classe também é uma Thread, ou seja, cada produtor será executado independentemente. O métodorun() também é bem semelhante ao do Consumidor, um laço que faz as chamadas ao buffer.
18 }
1234567
89101112131415161718
public class Produtor extends Thread { private int idProdutor; private Buffer pilha; private int producaoTotal;
public Produtor( int id, Buffer p, int producaoTotal) { idProdutor = id;
pilha = p; this .producaoTotal = producaoTotal; }
public void run() { for ( int i = 0; i < producaoTotal; i++) { pilha.set(idProdutor, i); } System.out.println( "Produtor #" + idProdutor + " concluido!" ); }}
-
8/18/2019 Praticando Concorrência Em Java! _ Marcos Brizeno
4/9
Sincronizando o acesso ao recurso compartilhado
Agora vem a parte principal, o buffer. Ele possui um conteúdo, que é colocado pelo produtor, e um booleano que indica quando oconteúdo está disponível.Para permitir que um produtor coloque um produto ela oferece um método set, que carrega o conteúdo e avisa para as outras thread produto está disponível. Para dar acesso ao Consumidor, o buffer oferece um método get, que devolve o conteúdo e avisa para outrathread que o produto não está mais disponível.
Esta classe merece uma atenção especial e será detalhada em partes menores. Primeiro veremos o método set():
Enquanto houver um conteúdo disponível no buffer, o produtor deve esperar. Quando o buffer não estiver mais com conteúdo dispoo conteúdo é carregado e as outras thread são notificadas que um novo conteúdo está disponível.
12
3456789
10111213
14
public synchronized void set( int idProdutor, int valor) { while (disponivel == true ) {
try { System.out.println( "Produtor #" + idProdutor + " esperando..." ); wait(); } catch (Exception e) { e.printStackTrace(); } } conteudo = valor; System.out.println( "Produtor #" + idProdutor + " colocou " + conteudo); disponivel = true ; notifyAll();
}
1234
public synchronized int get( int idConsumidor) { while (disponivel == false ) { try { System.out.println( "Consumidor #" + idConsumidor
-
8/18/2019 Praticando Concorrência Em Java! _ Marcos Brizeno
5/9
De forma semelhante ao Produtor, no método get o consumidor deve esperar enquanto não houver conteúdo disponível. Quando oconteúdo estiver disponível novamente o consumidor consome o recurso e notifca as outras thread que não há mais recurso disponív
O código completo da classe Buffer fica assim:
56789
101112
13141516
+ " esperado..." ); wait(); } catch (Exception e) { e.printStackTrace(); } } System.out.println( "Consumidor #" + idConsumidor + " consumiu: " + conteudo);
disponivel = false ; notifyAll(); return conteudo;}
123456789
101112131415161718192021
package br.concorrencia.produtorConsumidor; public class Buffer {
private int conteudo; private boolean disponivel;
public synchronized void set( int idProdutor, int valor) { while (disponivel == true ) { try { System.out.println( "Produtor #" + idProdutor + " esperando..." ); wait(); } catch (Exception e) { e.printStackTrace(); } } conteudo = valor; System.out.println( "Produtor #" + idProdutor + " colocou " + conteudo); disponivel = true ; notifyAll(); }
-
8/18/2019 Praticando Concorrência Em Java! _ Marcos Brizeno
6/9
O importante ai é verificar que os métodos get e set do buffer possuem um modificador especial: synchronized.Segundo [4], métodos sincronizados são uma estratégia simples para prevenir erros de interferência e inconsistência de memória. Seobjeto é acessado por mais de uma thread (o que no nosso exemplo é o objeto Buffer), todas as operações de escrita e leitura neste odevem ser feitas através de métodos sincronizados.
Para testar o nosso código, vamos criar o seguinte método main:
2223242526272829
30313233343536373839
public synchronized int get( int idConsumidor) {
while (disponivel == false ) { try { System.out.println( "Consumidor #" + idConsumidor + " esperado..." ); wait(); } catch (Exception e) {
e.printStackTrace(); } } System.out.println( "Consumidor #" + idConsumidor + " consumiu: " + conteudo); disponivel = false ; notifyAll(); return conteudo; }}
12
3456789
101112
public static void main(String[] args) { Buffer bufferCompartilhado = new Buffer();
Produtor produtor1 = new Produtor( 1, bufferCompartilhado, 5); Produtor produtor2 = new Produtor( 2, bufferCompartilhado, 5); Consumidor consumidor1 = new Consumidor( 1, bufferCompartilhado, 2); Consumidor consumidor2 = new Consumidor( 2, bufferCompartilhado, 8);
produtor1.start(); consumidor1.start(); produtor2.start(); consumidor2.start();}
-
8/18/2019 Praticando Concorrência Em Java! _ Marcos Brizeno
7/9
Criamos dois produtores e dois consumidores. Em seguida executamos o método da classe Thread chamado start(). Este método vaiinicializar a Thread e logo em seguida vai executar o método run(), que nós definimos nas classes Consumidor e Produtor.
Observando a saída no console, temos algo do tipo:
Produtor #1 colocou 0Produtor #1 esperando…Consumidor #1 consumiu: 0Consumidor #1 esperado…Produtor #1 colocou 1Produtor #1 concluido!Consumidor #1 consumiu: 1Consumidor #1 esperado…Produtor #2 colocou 0Produtor #2 esperando…Consumidor #2 consumiu: 0Consumidor #2 concluido!Produtor #2 colocou 1Produtor #2 concluido!Consumidor #1 consumiu: 1Consumidor #1 concluido!
A ordem de execução pode mudar pois a chamada aos Thread são feitas aleatoriamente em Java. Quando o método wait() na classe é executado, a Thread que está acessando ele fica em estado de espera. Quando o método notifyAll() é chamado, TODAS as Threadestão em espera são acordadas e executadas, por isso definimos um laço while nos métodos get e set, ou seja, a Thread só será libera
quando a condição for verdadeira.Uma discussão mais aprofundada sobre o assunto pode ser encontrada em [4]. No próximo post vamos ver alguns exemplos mais leusando semáforos de diversos tipos para controlar o acesso ao recurso compartilhado.
Obrigado pela visita, espero que este post tenha ajudado. Se gostou do post compartilhe com seus amigos e colegas, senão, comentepode ser melhorado. Encontrou algum erro no código? Comente também. Possui alguma outra opinião ou alguma informação adicioComenta ai!
-
8/18/2019 Praticando Concorrência Em Java! _ Marcos Brizeno
8/9
Referências:
[1] WIKIPEDIA. Monitor (concorrência). Disponível em: http://pt.wikipedia.org/wiki/Monitor_(concorrência)(http://pt.wikipedia.org/wiki/Monitor_(concorrência)). Acesso em: 23 set. 2011.[2] MARTIN, Robert C. Clean code: a handbook of agile software craftsmanship.[3] Sincronização de Threads. Disponível em: http://www.dsc.ufcg.edu.br/~jacques/cursos/map/html/threads/sincronizacao.html(http://www.dsc.ufcg.edu.br/~jacques/cursos/map/html/threads/sincronizacao.html). Acesso em 23 set. 2011.
[4] ORACLE. Synchronized Methods. Disponível em: http://download.oracle.com/javase/tutorial/essential/concurrency/syncmeth.h(http://download.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html). Acesso em 23 set. 2011.
Concorrência, Java Concorrência, Java, Semáforos 4 Comentários
4 comentários sobre “Praticando concorrência em Java!”
1.Thiago Braz
http://-/?-http://-/?-https://wordpress.com/about-these-ads/https://googleads.g.doubleclick.net/aclk?sa=L&ai=BuOid-zreVrTeF8WHxgT9h4VA4K3GhAgAAAAQASAAOABYwNzMzb8CYM2Qzo_8AoIBF2NhLXB1Yi0zNDQzOTE4MzA3ODAyNjc2sgEVYnJpemVuby53b3JkcHJlc3MuY29tugEJZ2ZwX2ltYWdlyAEC2gFJaHR0cHM6Ly9icml6ZW5vLndvcmRwcmVzcy5jb20vMjAxMS8wOS8yMy9wcmF0aWNhbmRvLWNvbmNvcnJlbmNpYS1lbS1qYXZhL8ACAuACAOoCEy85MjQwNzkyL2hvdXNlX21yZWP4Av_RHpADnASYA_ABqAMByAOZBNAEkE7gBAHSBQUQ4O3OUZAGAaAGFNgHAeAHCw&num=0&cid=5Ggsl9t6InvbpNNjP9CSlQFJ&sig=AOD64_1LXU44f-kTVw4zn5ZYSzVNfRbncg&client=ca-pub-3443918307802676&adurl=https://wordpress.com/create%3Futm_campaign%3Dhouseads%26utm_source%3Dcreate-website_passion_mrec_en.pnghttps://brizeno.wordpress.com/tag/semaforos/https://brizeno.wordpress.com/tag/java/https://brizeno.wordpress.com/tag/concorrencia/https://brizeno.wordpress.com/category/java/https://brizeno.wordpress.com/category/java/concorrencia/http://download.oracle.com/javase/tutorial/essential/concurrency/syncmeth.htmlhttp://www.dsc.ufcg.edu.br/~jacques/cursos/map/html/threads/sincronizacao.htmlhttp://pt.wikipedia.org/wiki/Monitor_(concorr%C3%AAncia)
-
8/18/2019 Praticando Concorrência Em Java! _ Marcos Brizeno
9/9
Cara mto bom, porem colokei aki para testar utilizando seu exemplo em um aplicação e da erro exatamente no metodo run doprodutor e consumidor empilha.set(idProdutor, i); e pilha.get(idConsumidor);
Responder
Thiago, isso aconteceu porque vc importou a classe Buffer do pacote java.nio.Buffer importe do pacote da classe Buffer criadexemplo.
Responder2.
Obrigado, excelente material ajudou muito a entender.
Responder3.
Ótimo Exemplo, mais o programa está dando erro nos métodos get e set das Classes Produtor e Consumidor além de estar sendoexigido um método que exceção dentro das respectivas classes, método esse que não é citado no seu exemplo.
Método:
Produtor(int i, Classes.Buffer bufferCompartilhado, int i0) {throw new UnsupportedOperationException(“Not supported yet.”); //To change body of generated methods, choose Tools |Templates.}
Responder
Blog no WordPress.com. | O tema Highwind.
Eduardo
Mateus Getulio Vieira
Anônimo
http://-/?-http://-/?-http://-/?-http://www.facebook.com/100004301494647https://wordpress.com/themes/highwind/https://br.wordpress.com/?ref=footer_bloghttps://brizeno.wordpress.com/2011/09/23/praticando-concorrencia-em-java/?replytocom=488#respondhttps://brizeno.wordpress.com/2011/09/23/praticando-concorrencia-em-java/?replytocom=475#respondhttps://brizeno.wordpress.com/2011/09/23/praticando-concorrencia-em-java/?replytocom=496#respondhttps://brizeno.wordpress.com/2011/09/23/praticando-concorrencia-em-java/?replytocom=78#respond