java 实现生产者-消费者模式

生产和消费者模式有很多种,现在介绍几种常见的方式

  •   wait/notify实现生产和消费者模式

1、使用wait/notify实现生产和消费者模式:

public class Depot {

    // 实际容量
    private volatile int capacity = 0 ;
    // 最大容量
    private static final int MAX_CAPACITY = 100 ;
    //
    private final Object lock = new Object() ;

    public Depot(){
        
    }

    /**
     *  生产
     * @param: num
     * @return:
     */
    public void producer(int num) {
        if(num<0){
            System.out.println("生产数量不可为负数");
            throw new IllegalArgumentException("生产数量不可为负数") ;
        }

        synchronized (lock){
            // 生产
            int left = 0;
            try {
                left = doProducer(num);

                // 要求生产数量未达标,让出执行权
                while (left > 0){
                    Thread.yield();
                    left = doProducer(left);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            lock.notify();
        }

    }

    /**
     *  实际生产逻辑
     * @param: num
     * @return: 返回未生产数量
     */
    private int doProducer(int num) throws InterruptedException {
        // 实际增加数量
        int grow = num ;
        // 未生产数量
        int left = 0 ;

        // 等待仓库被消费
        while (capacity>=MAX_CAPACITY){
            lock.wait();
        }

        // 计算实际新增数量
        if( (num+capacity) > MAX_CAPACITY ){
            grow = MAX_CAPACITY - capacity ;
            left = num - grow ;
        }
        capacity += grow ;

        // 仓库已经生产,通知消费者消费
        lock.notify();
        System.out.println(Thread.currentThread().getName() + " Plan Producer = " + num + " Actually = " + grow + " left =  " + left + "  capacity = " + capacity);
        return left ;
    }

    /**
     *  消费
     * @param: num
     * @return:
     */
    public void consumer(int num) {
        if(num<0){
            System.out.println("消费数量不可为负数");
            throw new IllegalArgumentException("消费数量不可为负数") ;
        }

        synchronized (lock){
            // 消费仓库
            int left = 0;
            try {
                left = doConsumer(num);

                // 要求消费数量未达标,让出执行权
                while (left > 0){
                    Thread.yield();
                    left = doConsumer(left);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            // 仓库已经被消费,通知生产者生产
            lock.notify();
        }

    }

    /**
     *  实际消费逻辑
     * @param:   num
     * @return:  剩余未消费数量
     */
    private int doConsumer(int num) throws InterruptedException {
        // 实际消费数量
        int decrease = num ;
        // 剩余未消费
        int left = 0 ;

        // 等待仓库生产
        while (capacity <= 0){
            lock.wait();
        }

        // 计算实际消费数量
        if(decrease > capacity){
            decrease = capacity ;
            left = decrease - capacity ;
        }
        capacity -= decrease ;

        System.out.println(Thread.currentThread().getName() + " Plan Consumer = "+ num + " Actually = " + decrease + " left =  " + left + "  capacity = " + capacity );
        return left ;
    }

}

测试案例:

public class ProducerAndConsumer {
    public static void main(String[] args) throws InterruptedException {
        Depot depot = new Depot() ;

        for(int x=0 ; x<4; x++){
            new Thread(new Runnable() {
                @Override public void run() {
                    depot.producer(40);
                }
            }).start();
        }

        Thread.sleep(2000L);
        for(int x=0 ; x<3; x++){
            new Thread(new Runnable() {
                @Override public void run() {
                    depot.consumer(40);
                }
            }).start();
        }

        Thread.sleep(2000L);

    }
}

运行结果:

Thread-0 Plan Producer = 40 Actually = 40 left =  0  capacity = 40
Thread-1 Plan Producer = 40 Actually = 40 left =  0  capacity = 80
Thread-2 Plan Producer = 40 Actually = 20 left =  20  capacity = 100
Thread-4 Plan Consumer = 40 Actually = 40 left =  0  capacity = 60
Thread-2 Plan Producer = 20 Actually = 20 left =  0  capacity = 80
Thread-3 Plan Producer = 40 Actually = 20 left =  20  capacity = 100
Thread-6 Plan Consumer = 40 Actually = 40 left =  0  capacity = 60
Thread-5 Plan Consumer = 40 Actually = 40 left =  0  capacity = 20
Thread-3 Plan Producer = 20 Actually = 20 left =  0  capacity = 40

其他待续.........

原文地址:https://www.cnblogs.com/xiaoxing/p/8556236.html