luni, 15 februarie 2010

Java: Problema producator - consumator

//Clasa Producator


public class Producator extends Thread {
private Produs copieProdus;
public Producator(Produs produs){ //constructor
copieProdus=produs;
}
public void run(){
for(int i=0;i<10;i++){ //incearca sa "creeeze" 10 produse
copieProdus.set(i);
try{
sleep(500);
}
catch(Exception ex){
System.out.println("Exceptie producator");
}
}
}
}

//Clasa Consumator


public class Consumator extends Thread{
private Produs copieProdus;
public Consumator(Produs produs){
copieProdus=produs;
}
public void run(){
for(int i=0;i<10;i++){
copieProdus.get(); //incearca sa "consume" 10 produse
try{
sleep(500);
}
catch(Exception ex){
System.out.println("Exceptie Consumator");
}
}
}
}


//Clasa produs


public class Produs {
private boolean available=false;
private int container=-1;
public synchronized void set(int valoare){
while(available==true){
try{
wait(5000); //blocheaza firul solicitant daca avem deja creat un obiect
//Thread.sleep(50);
}
catch(Exception ex){
System.out.println("Eroare set");
}
}
available=true;//pentru ca, consumatorul sa poata consuma
container=valoare;
System.out.println("Setare produs: "+container);
notifyAll();//deblocheaza toate firele, in cazul de fata ofera o sansa consumatorului
}
public synchronized int get(){
while(available==false){
try{
wait(5000);//blocheaza firul solicitant daca nu avem creat un obiect
//Thread.sleep(50);
}
catch(Exception ex){
System.out.println("Eroare get");
}
}
available=false;//pentru ca, producatorul sa poata sa produca
System.out.println("Consumare produs: "+container);
notifyAll();//deblocheaza toate firele, in cazul de fata ofera o sansa producatorului
return container;
}
}

//Clasa Main


public class Main {
public static void main(String[] args){
Produs produs=new Produs();
Consumator consumator=new Consumator(produs);
Producator producator=new Producator(produs);
producator.start();
consumator.start();
}
}



/**Modul de functionare:
* In clasa Main se face o instanta a Produsului, si este trimisa ca si parametru Consumatorului si Producatorului. Se pornesc metodele start ale Threadurilor
* Atat Producatorul cat si Consumatorul incearca sa faca de 10 ori operatia de set/get din Produs.
* Daca nu se pot face get/set din Produs, prin folosirea lui wait() se va bloca Consumatorul/Producatorul, blocarea putandu-se realiza doar unei categorii
* Un ex. posibil de functionare: Consumatorul obtine cheia Produsului si incearca accesarea metodei get(); daca avem o valoare in Produs, atunci citirea se face cu succes(nu intra pe while) si se deblocheaza Producatorul; daca nu avem valoare, se intra pe while si se blocheaza Consumatorul
* Producatorul obtine cheia Produsului incearca sa faca o inscriere, daca nu avem valoare in Produs se va putea si se deblocheaza Consumatorul, daca vem deja o valoare se va bloca Producatorul
* OBS: Metodele wait() si notifyAll() se pot folosi in metodele sincronizate mult mai eficient decat Thread.sleep(). Un obiect blocat cu wait se va debloca dupa trecerea timpului sau prin apelare notify, notifyAll. Se evita astfel blocajele(decomenteaza sleep si comenteaza notifyAll si wait in acest ex).
* Fie 3 fire:1,2,3; daca firul 3 se poate executa doar dupa terminarea activitatii firelor 1 si 2 putem uni cele 2 fire prin join ex: fir2.join();
* Se pot de asemenea folosi si 2 Producatori si 2 Consumatori */

Vezi: Thread si Introducere in universul Java, Horia Georgescu, Ed. Tehnica 2002.

Niciun comentariu:

Trimiteți un comentariu