生产者模式实现总结2

第二种方法摘自: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)的的方法。在这个队列中,可以放入“产品”,如果队列中没有产品,消费者去“消费”的话会自动挂起消费者,知道队列中加入了新的“商品”;

原文地址:https://www.cnblogs.com/mengyan/p/2664379.html