praticando concorrência em java! _ marcos brizeno

Upload: vinicius-goncalves

Post on 07-Jul-2018

214 views

Category:

Documents


0 download

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