Na verdade, não estou usando um monitor com um objeto, mas sim um método com synchronized.
public interface Buffer
{
public void set(int value);
public int get();
}
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class SynchronizedBufferComSynchronized implements Buffer
{
private int buffer = -1;
private boolean full;
public synchronized void set(int value)
{
while(full)
{
try
{
System.out.println("Produtor tenta produzir");
displayState("Buffer cheio. Produtor espera.");
wait();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
this.buffer = value;
full = true;
displayState("Produtor escreve "+this.buffer);
notify();
}
public synchronized int get()
{
while(!full)
{
try
{
System.out.println("Consumidor tenta consumir");
displayState("Buffer vazio. Consumidor espera.");
wait();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
full = false;
displayState("Consumidor consome "+this.buffer);
notify();
return this.buffer;
}
public void displayState(String mensagem)
{
System.out.printf("%-40s%d\t\t%b\n\n", mensagem, this.buffer, full);
}
}
import java.util.Random;
public class Produtor implements Runnable
{
private static Random r = new Random();
private Buffer sharedLocation;
public Produtor(Buffer b)
{
sharedLocation = b;
}
public void run()
{
int soma = 0;
for(int i = 0; i <= 10; i++)
{
try
{
Thread.sleep(r.nextInt(2000));
sharedLocation.set(i);
soma+=i;
System.out.printf("\t%sd\n", soma);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
System.out.printf("\n%s\n%s\n", "Produtor acaba de produzir", "Terminando produtor.");
}
}
import java.util.Random;
public class Consumidor implements Runnable
{
private static Random r = new Random();
private Buffer b;
private int value;
public Consumidor(Buffer sharedBuffer)
{
b = sharedBuffer;
}
public void run()
{
int soma = 0;
try
{
for(int i = 0; i <= 10; i++ )
{
Thread.sleep(2000);
//value = b.get();
soma += b.get();
System.out.printf("\t\t\t%2d\n", soma);
}
}
catch(InterruptedException e)
{
e.printStackTrace();
}
System.out.printf("\n%s\n%s\n", "Consumidor lê valores", soma, "Terminando consumidor.");
}
}
O método set terá sempre apenas uma thread dentro. O mesmo para get.
Mas nada impede de ter uma thread dentro de get e outra em set, não é?
Essa é a dúvida.
Na main, faço somente…
public static void main(String []args)
{
ExecutorService application = Executors.newFixedThreadPool(2);
Buffer b = new SynchronizedBufferComSynchronized();
application.execute(new Produtor(b));
application.execute(new Consumidor(b));
application.shutdown();
}
Eu pensei no seguinte.
Eu imagino que enquanto uma thread esetja em “set”, o sistema operacional pode parar e execução dessa, seja, por exemplo, porque o seu quantum terminou, e outra thread seja escalonada. Essa outra thread executa em “get”. Nada impede, no código acima, que a segunda thread entre em “get”.
Quando eu usava Condition, eu tinha esse controle…