如果没记错在gof的23种设计模式里面并没有涉及到生产者与消费者模式,记得很就以前有个面试官叫我讲解下生产者与消费者模式,当时我就闷了,我就一直不停的在记忆中从23种模式搜索,结果无论如何都是想不起来,所以很尴尬了。
好吧,废话不多说
有这样一个饭店,他有一个厨师和一个服务员。这个服务员必须等待厨师准备好膳食。当厨师准备好时,他会通知服务员,之后服务员上菜,然后返回继续等待。这是一个协作的示例:两个任务必须在膳食被生产和消费时进行握手,厨师是生产者,服务员是消费者,而系统必须有序的方式关闭。
以下是代码,比较简单的一个小例子。
Meal.java
package com.cs.model; /** * 膳食 * @author chinasoft * */ public class Meal { private final int orderNum; public Meal(int orderNum) { this.orderNum = orderNum; } @Override public String toString() { return "meal" + orderNum; } }
Chef .java
package com.cs.person; import java.util.concurrent.TimeUnit; import com.cs.model.Meal; import com.cs.run.Restaurant; /** * 厨师 * @author chinasoft * */ public class Chef implements Runnable { private Restaurant restaurant; private int count = 0; public Chef(Restaurant restaurant) { this.restaurant = restaurant; } @Override public void run() { try { while (!Thread.interrupted()) { synchronized (this) { while (restaurant.meal != null) { System.out.println("Chef wait"); wait(); } } if (++count == 10) { System.out.println("out food is closing"); restaurant.exec.shutdownNow(); } System.out.println("Order up!"); synchronized (restaurant.waitPerson) { restaurant.meal = new Meal(count); restaurant.waitPerson.notifyAll(); } //由于生产者提供的较快 可以让他速度慢点,以免出现等待现象 TimeUnit.MICROSECONDS.sleep(100); } } catch (InterruptedException e) { System.out.println("Chef interrupted"); } } }
WaitPerson.java
package com.cs.person; import com.cs.run.Restaurant; /** * 服务员 * @author chinasoft * */ public class WaitPerson implements Runnable { private Restaurant restaurant; public WaitPerson(Restaurant restaurant) { this.restaurant = restaurant; } @Override public void run() { try { while (!Thread.interrupted()) { synchronized (this) { while (restaurant.meal == null) wait(); } System.out.println("WaitPerson got" + restaurant.meal); synchronized (restaurant.chef) { restaurant.meal = null; //这里理论上是调用notify(),但是,在更复杂的情况下,可能有多个任务给对象上锁 //而你不知道是哪个任务,所以调用notifyAll更加安全 restaurant.chef.notifyAll(); } } } catch (InterruptedException e) { System.out.println("waitPerson interrupt"); } } }
Restaurant.java
package com.cs.run; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import com.cs.model.Meal; import com.cs.person.Chef; import com.cs.person.WaitPerson; /** * 餐厅 * @author chinasoft * */ public class Restaurant { public Meal meal; public Chef chef = new Chef(this); public WaitPerson waitPerson = new WaitPerson(this); /** 执行线程池*/ public ExecutorService exec = Executors.newCachedThreadPool(); public Restaurant() { exec.execute(chef); exec.execute(waitPerson); } public static void main(String[] args) { new Restaurant(); } }