您的位置:首页 > 其它

生产者模式实现总结2

2012-08-30 20:44 211 查看
第二种方法摘自:think in java

下面我们简化一下这个例子。以Think in Java中的例子为原形。大致是这样的,我们将生产者看成是餐厅里的厨师,消费者看成是餐厅里的服务员。厨师会不停的做出食物,而服务员会将厨师做出的食 物拿给顾客。刚开始服务员是处于等待阶段,直到厨师将食物做出来后,他会通知服务员将食物拿走。这时厨师会处于等待阶段,直到服务员将食物拿走后,他会通 知厨师可以继续生产食物。下面是这个例子的代码:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class Restaurant {
Meal meal;
ExecutorService exec = Executors.newCachedThreadPool();
WaitPerson waitPerson = new WaitPerson(this);
Chef chef = new Chef(this);

class Meal {
private final int orderNum;

public Meal(int orderNum) {
this.orderNum = orderNum;

}

public String toString() {
return "Meal" + orderNum;
}
}

class Chef implements Runnable {
private Restaurant restaurant;
private int count;

public Chef(Restaurant r) {
restaurant = r;
}

@Override
public void run() {
// TODO Auto-generated method stub
try {
while (!Thread.interrupted()) {
// 获取自己本身的对象锁
synchronized (this) {
// 如果restaurant中的meal不为空,继续等待
while (restaurant.meal != null) {
wait();// waiter等待meal不为空
}
}
System.out.println(count);
if(++count==10)
{
System.out.println("out of food,closing");
restaurant.exec.shutdownNow();//停止线程
}
System.out.println("order up");
// 获得chef的对象锁,以便于通知chef及时执行操作
synchronized (restaurant.waitPerson) {
restaurant.meal=new Meal(count);
restaurant.waitPerson.notifyAll();

}
}

} catch (InterruptedException e) {

}
}
}

class WaitPerson implements Runnable {
private Restaurant restaurant;

public WaitPerson(Restaurant r) {
restaurant = r;
}

@Override
public void run() {
// TODO Auto-generated method stub
try {
while (!Thread.interrupted()) {
// 获取自己本身的对象锁
synchronized (this) {
// 如果restaurant中的meal为空,循环执行
while (restaurant.meal == null) {
wait();// waiter等待meal不为空
}
}
System.out.println("WaitPerson got  " + restaurant.meal);
// 获得chef的对象锁,以便于通知chef及时执行操作
synchronized (restaurant.chef) {
restaurant.meal = null;// 取走meal
restaurant.chef.notifyAll();// 通知chef可以制造meal

}
TimeUnit.MILLISECONDS.sleep(100);
}
} catch (InterruptedException e) {

}

}
}
Restaurant()
{
exec.execute(chef);
exec.execute(waitPerson);
}

public static void main(String[] args)
{
new Restaurant();

}

}


在这个例子中,并没有用到共享内存(Restaurant)中的同步方法,而是通过在共享内存中获取各个线程的引用,并通过它们加锁后然后相互进行通知,这里使用到了“点对点”通知的方法,即生产者只通知消费者,而不会额外去通知其它生产者。

问题:

在上面的方式显然不太适合多生产者-仓库-多消费者这种模式,这也是它的弊端所在。而在上篇文章介绍的第一种方法里,可以利用共享内存的同步方法,对多个生产者和消费者进行同步!但是这些方法始终都有一个问题,那就是制作效率不高,在同步方法里面,每一时刻只能有一个方法在运行,不能起到多个生产者或多个消费者同时运行,增加“生产能力”/“消费能力”;

备注:

这种方式在java里实现是有些稍显笨拙;在think in java中还介绍了一种生产者-消费者队列(BlockingQueue)的的方法。在这个队列中,可以放入“产品”,如果队列中没有产品,消费者去“消费”的话会自动挂起消费者,知道队列中加入了新的“商品”;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: