* Consumer-Producer – едностранна синхронизация с много консуматори и един производител
Публикувано на 29 ноември 2013 в раздел ПИК3 Java.
В този пример има споделен ресурс – чиния с храна. За нея няма ограничение какво количество храна ще поеме, затова producer (в случая Human) ще я пълни още и още независимо дали е пълна или празна. Кучетата ще се редят едно след друго и ще чакат да се напълни чинията. Използва се централен mutex, с който кучето заявява пред човека, че търси "събуждане" (notify). Това се прави, за да се предотврати race condition, в който две кучета са събудени последователно и второто изяжда съдържанието на празна чиния (първото е изяло всичко, а човекът все още не е успял да сготви ново ястие). Освен това чинията вече е направена като обект, за да може да се синхронизира по него. По този начин се избягва race condition, при който човекът сготвя ястия в периода между пълненето на стомаха на кучето и нулирането на съдържанието на чинията.
public class CP{
static Dish dish = new Dish();
static Dog sharo1 = new Dog("Sharo1");
static Dog sharo2 = new Dog("Sharo2");
static Dog sharo3 = new Dog("Sharo3");
static Human ivan = new Human();
static volatile boolean mutex = false;
public static void main(String[] args){
sharo1.start();
sharo2.start();
sharo3.start();
ivan.start();
}
}
class Dish{
int dish;
public Dish(){
this.dish = 0;
}
}
class Dog extends Thread{
int stomach;
boolean feeded;
String name;
public Dog(String name){
this.name = name;
this.stomach = 0;
this.feeded = false;
}
public void run(){
while(this.stomach <= 100){
try{
this.getFood();
}
catch(InterruptedException e){
System.out.println(this.name+" will not feed full");
break;
}
}
System.out.println(this.name+": Woof, woof!");
this.feeded = true;
CP.mutex = true;
}
void getFood() throws InterruptedException{
synchronized(CP.ivan){
if(CP.dish.dish ==0){
System.out.println(this.name+" waiting for food");
CP.mutex = true; // ivan should notify me
CP.ivan.wait();
}
this.sleep((int)(Math.random()*500)); // Dog eats
synchronized(CP.dish){
System.out.println(this.name+" eats "+CP.dish.dish);
this.stomach+=CP.dish.dish;
CP.dish.dish = 0;
}
}
}
}
class Human extends Thread{
public void run(){
do{
try{
this.cookFood();
}
catch(InterruptedException e){
System.out.println("Human stopped cooking");
break;
}
}
while( CP.sharo1.feeded == false
|| CP.sharo2.feeded == false
|| CP.sharo3.feeded == false);
}
void cookFood() throws InterruptedException{
synchronized(CP.dish){
this.sleep((int)(Math.random()*100)); // Human cooks
CP.dish.dish += 10;
}
System.out.println("Human cooked 10. Dish = "+CP.dish.dish);
if(CP.mutex){
synchronized(this){
this.notify();
}
CP.mutex = false; // I should not notify more dogs yet
}
}
}
Добави коментар