3.1 - Classe BufferCircular.java

            
package br.aiec.multithread.monitor;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import br.aiec.multithread.comum.IBuffer;

/**
 * Essa classe representa um monitor de fato, e, portanto,
 * 
 * ELA É SEGURA PARA MULTITHREAD!
 * 
 * Essa classe oferece um mecanismo de sincronização para acesso
 * concorrente/paralelo ao buffer circular, o que consequentemente, irá garantir a
 * integridade no buffer.
 * 
 * 
 *  
 * 
 */

public class BufferCircular implements IBuffer {

    /**
     *  Variáveis utilizadas garantir o acesso exclusivo
     */
    private Lock bloqueio;
    private int w; // semáforo exclusivo do produtor (indice de gravação)
    private int r; // semáforo exclusivo do consumidor (indice de leitura)
    private int quantidade; // semáforo de uso compartilhado pelo produtor e consumidor

    /**
         *  Variáveis utilizadas para guardar os sinais e
         *  permitir transitar as threads entre os estados de executável -> espera e vice-versa
         */ 
    private Condition podeGravar;
    private Condition podeLer;

    // Variável compartilhada
    private int buffer[];

    public BufferCircular() {
        bloqueio = new ReentrantLock();
        podeGravar = bloqueio.newCondition();
        podeLer = bloqueio.newCondition();
        buffer = new int[5];

        // Essas três inicializações abaixo são desnecessárias, pois o Java já
                // faria isso! Foram escritas apenas para tornar o código mais claro!
        w = 0;
        r = 0;
        quantidade = 0;
    }

    @Override
    public void gravar(int value) {

        try {
            bloqueio.lock();

            while (quantidade == buffer.length) {
                System.out.println("Produtor esperando... Buffer cheio!");
                podeGravar.await();
            }

            System.out.println("GRAVANDO - BUFFER["+ w + "]: " + value);
            
            this.buffer[w] = value;
            
            this.quantidade++;
            
            w = (w + 1) % buffer.length;
            
            podeLer.signal();

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            bloqueio.unlock();
        }
    }

    @Override
    public int ler() {
        int value = 0;
        
        try {
            bloqueio.lock();

            while (quantidade == 0) {
                System.out.println("Consumidor esperando... Buffer vazio!");
                podeLer.await();
            }

            System.out.println("LENDO - BUFFER["+ r + "]: " + this.buffer[r]);
            
            value = this.buffer[r];
            
            this.quantidade--;
            
            r = (r + 1) % buffer.length;
            
            podeGravar.signal();

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            bloqueio.unlock();
        }
        
        return value;
    }
}

            
        
Copyright © 2016 AIEC.