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;
}
}