天天看点

生产者与消费者设计模式

1. 原理

它描述的是有一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者可以从仓库中取走产品,解决生产者/消费者问题,我们需要采用某种机制保护生产者和消费者之间的同步
同步问题核心在于:如何保证同一资源被多个线程并发访问时的完整性,常用的方法就是加锁,保证资源在任意时刻只被一个线程访问      

画图分析:

生产者与消费者设计模式

2. 实现

采用wait()、notify()和notifyAll()方法
wait():当缓冲区已满或空时,生产者/消费者线程停止自己的执行,放弃锁,使自己处于等待状态,让其他线程执行

    ·是Object的方法
    ·调用方式:对象.wait();
    ·表示释放 对象 这个锁标记,然后在锁外边等待(对比sleep(),sleep是抱着锁休眠的)
    ·等待,必须放到同步代码段中执行      
notify():当生产者/消费者向缓冲区放入/取出一个产品时,向其他等待的线程发出可执行的通知,同时放弃锁,使自己处于等待状态

    ·是Object的方法
    ·调用方式:对象.notify();
    ·表示唤醒 对象 所标记外边在等待的一个线程      
notifyAll():全部唤醒

    ·是Object的方法
    ·调用方式:对象.notifyAll()
    ·表示唤醒  对象 所标记外边等待的所有线程      
/**
 * @author bruceliu
 * @create 2019-06-01 22:04
 * @description
 */
public class ProductorAndConsumerDemo01 {
    // 定义一个标记,用来表示产品是否需要被生产
    static boolean shouldProduct = true;

    static Object o=new Object();

    // 静态成员内部类
    // 生产者线程的target
    static class Productor implements Runnable {
        //需要生产的产品
        private Product p;

        public Productor(Product p) {
            this.p = p;
        }


        @Override
        public void run() {
            while (true) {
                synchronized (o) {
                    if (shouldProduct) {
                        //生产
                        this.p.setName("老婆饼");
                        System.out.println("生产者" + Thread.currentThread().getName() + "生产了一件产品" + this.p);

                        //修改状态
                        shouldProduct = false;

                        //通知消费者来进行消费
                        o.notifyAll();
                    } else {
                        //等待
                        try {
                            o.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

    //消费者线程的target
    static class Consumer implements Runnable {
        //需要被消费的产品
        private Product p;

        public Consumer(Product p) {
            this.p = p;
        }

        @Override
        public void run() {
            while (true) {
                synchronized (o) {
                    if (shouldProduct) {
                        try {
                            o.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    } else {
                        //消费
                        System.out.println("消费者" + Thread.currentThread().getName() + "消费了一件产品" + this.p);
                        //修改状态
                        shouldProduct = true;
                        //通知生产者去生产
                        o.notifyAll();
                    }
                }
            }
        }
    }

    public static void main(String[] args) {
        //说明:如果锁外面只有一个生产者或者一个消费者等待的话,则使用notify唤醒,
        //但是,如果锁外面有多个生产者或者多个消费者等待的话,则使用notifyAll唤醒
        //实例化一个产品
        Product p = new Product();

        //生产者
        Productor productor = new Productor(p);
        Thread t0 = new Thread(productor,"老王头");
        Thread t1 = new Thread(productor,"老李头");
        t0.start();
        t1.start();

        //消费者
        Consumer consumer = new Consumer(p);
        Thread thread0 = new Thread(consumer,"小凳子");
        Thread thread1 = new Thread(consumer,"小桌子");
        thread0.start();
        thread1.start();

    }
}

class Product {
    private String name;
    private int id;

    public void setName(String name) {
        this.name = name;
        id++;
    }

    @Override
    public String toString() {
        return "Product [name=" + name + ", id=" + id + "]";
    }
}