生产者和消费者模型

131 阅读2分钟
/**
 * 参考资料:https://blog.csdn.net/SheIsSDEatNYC/article/details/108571729
 * 生产者-消费者模型,主要实现两者之间的解耦、异步和平衡速度差异。
 * 如果队列里的产品已经满了,生产者就不能继续生产;
 * 如果队列里的产品从无到有,生产者就得通知一下消费者,告诉它可以来消费了;
 * 如果队列里已经没有产品了,消费者也无法继续消费;
 * 如果队列里的产品从满到不满,消费者也得去通知下生产者,说你可以来生产了。
 * 它们之间的协作,就是使用Object类里自带的wait()和notify()或者notifyAll()的消息通知机制。
 * wait()方法是用来让当前线程等待,直到有别的线程调用notify()将它唤醒,或者我们可以设定一个时间让它自动苏醒。
 * 调用notify方法之前,线程必须要获得该对象的对象监视器锁,也就是只能用在加锁的方法下。而调用该方法之后,当前线程会释放锁。
 * notify()方法只能通知一个线程,如果多个线程在等待,那就唤醒任意一个。
 * notifyAll()方法是可以唤醒所有等待线程,然后加入同步队列。
 */
public class ProducerAndConsumerDemo {

    public static void main(String[] args){
        Queue<Product> queue = new ArrayDeque<>();
        for(int i=0;i<100;i++){
            new ProducerThread(queue,100).start();
            new ConsumerThread(queue,100).start();
        }
    }

    /**
     * 生产者
     */
    static class ProducerThread extends Thread{
        private Queue<Product> queue;
        private int maxCapacity;
        public ProducerThread(Queue<Product> queue,int maxCapacity){
            this.queue = queue;
            this.maxCapacity = maxCapacity;
        }
        @Override
        public void run(){
            /**
             * 生产者线程拿到锁后,其实就是进入了运行中阶段。
             * 首先检查队列是否容量已满,如果满了,那就要去等待;
             * 如果不满,先检查一下队列原本是否为空,如果原来是空的,那就需要通知消费者;最后生产产品。
             */
            synchronized (queue){
                // 如果没有地方暂存商品,则进入等待
                while(queue.size()==maxCapacity){
                    System.out.println("当前生产者"+Thread.currentThread().getName()+"生产商品无法暂存,将进入等待中");
                    try {
                        queue.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                // 如果暂存的商品为0,则开始生产的时候,需要通知在等待的消费线程
                if(queue.isEmpty()){
                    queue.notifyAll();
                }
                Product product = new Product(String.valueOf(new Random().nextInt()));
                queue.offer(product);
                System.out.println("当前生产者"+Thread.currentThread().getName()+"生产商品"+product.name);
            }
        }
    }


    /**
     * 消费者
     */
    static class ConsumerThread extends Thread{
        private Queue<Product> queue;
        private int maxCapacity;
        public ConsumerThread(Queue<Product> queue,int maxCapacity){
            this.queue = queue;
            this.maxCapacity = maxCapacity;
        }
        @Override
        public void run(){
            synchronized (queue){
                // 如果没有商品可消费,则进入等待
                while(queue.isEmpty()){
                    System.out.println("当前消费者"+Thread.currentThread().getName()+"无商品可消费,将进入等待");
                    try {
                        queue.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("当前消费者"+Thread.currentThread().getName()+"无商品可消费等待结束");
                }
                // 如果暂存的商品以满,则开始消费的时候,需要通知在等待的生产线程
                if(queue.size()==maxCapacity){
                    queue.notifyAll();
                }
                System.out.println("当前消费者"+Thread.currentThread().getName()+"消费商品"+queue.poll().name);
            }
        }
    }

    static class Product{
        /**
         * 商品的名称
         */
        private String name;

        public Product(String name){
            this.name = name;
        }
    }
}