Java wait/notify方式实现生产者消费者问题

商品类

class Goods{
    public Goods() {}
}

生产者

class Producer extends Thread{
    Container container;
    public Producer(Container container){
        this.container = container;
    }
    @Override
    public void run() {
        for(int i = 0;i<20;i++){
            container.produce(new Goods());
        }
    }
}

消费者

class Consumer extends Thread{
    Container container;
    public Consumer(Container container){
        this.container = container;
    }
    @Override
    public void run() {
        for(int i = 0;i<20;i++){
            container.consume();
        }
    }
}

货物容器

class Container{
    private final  int CONTAINER_CAPACITY = 5;
    private LinkedList<Goods> container = new LinkedList<>();
    public synchronized void produce(Goods goods) {//模拟生产
        while(container.size() == container_Capacity){ //当前容器的货物满了
            try {
                System.out.println("仓库已满");
                this.wait();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        container.add(goods);
        System.out.println("【生产】货物,现有库存"+container.size());
        this.notifyAll();
    }

    public synchronized void consume(){//模拟消费
        while(container.size() == 0){//当前容器为空
            try {
                System.out.println("仓库为空");
                this.wait();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        container.remove();
        System.out.println("【消费】货物,现有库存"+container.size());
        this.notifyAll();
    }
}

测试

public class SynDemo {
    public static void main(String[] args) {
        Container container = new Container();
        new Producer(container).start();
        new Consumer(container).start();
    }
}

虚假唤醒Spurious Wakeup

"This means that when you wait on a condition variable, the wait may (occasionally) return when no thread specifically broadcast or signaled that condition variable. Spurious wakeups may sound strange, but on some multiprocessor systems, making condition wakeup completely predictable might substantially slow all condition variable operations. The race conditions that cause spurious wakeups should be considered rare."---wikipedia。


当存在多位生产者与消费者时,同步方法中使用if判断一个条件满足,多个线程被返回。

解决方案

使用while循环包围条件变量等待操作

ReentrantLock与Condition实现

class Container<goods> {
    private final  int CONTAINER_CAPACITY = 5;
    private LinkedList<Goods> container = new LinkedList<>();
    ReentrantLock lock = new ReentrantLock();
    Condition condition = lock.newCondition();
    public void produce(Goods goods) {//模拟生产
        lock.lock();
        try {
            while(container.size() == container_Capacity){ //当前容器的货物满
                System.out.println("仓库已满");
                condition.await();
            }
            container.add(goods);
            System.out.println(Thread.currentThread().getName()+"【生产】货物,现有库存"+container.size());
            condition.signal();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public void consume(){//模拟消费
        lock.lock();
        try {
            while(container.size() == 0){//当前容器为空
                System.out.println("仓库为空");
                condition.await();
            }
            container.remove();
            System.out.println(Thread.currentThread().getName()+"【消费】货物,现有库存"+container.size());
            condition.signal();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
}

参考文档
wikipedia_Spurious_wakeup

posted @ 2021-05-05 20:12  Ho-Yu-Fung  阅读(119)  评论(0编辑  收藏  举报