* 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 } } }
Добави коментар