多线程-生产者消费者模式-CopyOnWriteArrayList索引越界问题

为什么消费者会出现索引越界呢?

因为缓冲区消费判定时候使用了if判断,wait() 被叫醒后,如果其他线程已经抢到了对象锁并且已经消费了一个产品后,那么产品就为0了,现在直接进行取产品就会发生索引越界,所以此时应该使用while循环  使其一直判定  是否为0  是0就等待  继续抢 往复循环

缓冲区:

public class OrderPool {
    private CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();

    //生产者放入订单
    public synchronized void produceOrder() {
        while (list.size() == 30) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        list.add("order");
        this.notifyAll();
        System.out.println(Thread.currentThread().getName() + "---->生产一个订单,还有" + list.size() + "个订单");
        try {
            TimeUnit.MILLISECONDS.sleep(300L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    /**
     * 为什么下面判断条件用if的时候会报索引越界呢?
     * 因为该线程醒了之后要再次判断是否为0
     * 因为不知道等待的时候其他线程是否更新了  list.size()
     * 若此时其他消费者已经消费了商品 但是自己又没有判断lise.size() 是否为0 此时取出第一个订单  就会出现索引越界
     * 所以此时应该使用while一直判断是否为0 如果为0  继续等待
     */
    public synchronized void consumerOrder() {
        while (list.size() == 0) {
            System.out.println("订单池没有订单,消费者等待中");
            try {//只能用在同步方法 或者同步代码块中
                /*调用wait()方法后 立刻释放对象锁  线程进入当前对象的等待池
                 * 被唤醒之后,要拿到对象锁后才可以继续执行
                 * 若没有拿到对象锁  则会一直等待*/
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //若订单池中有订单 就消耗一个订单
        list.remove(0);
        // this.notify(); 也是只能出现在同步代码块中  notify() 随机唤醒一个线程
        this.notifyAll();
        System.out.println(Thread.currentThread().getName() + "---->消费一个订单,还有" + list.size() + "个");
        try {
            TimeUnit.MILLISECONDS.sleep(200L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

消费者:

public class Consumer implements Runnable {
    private OrderPool orderPool;

    public Consumer() {
    }

    public Consumer(OrderPool orderPool) {
        this.orderPool = orderPool;
    }

    @Override
    public void run() {
        while (true) {
            orderPool.consumerOrder();
        }

    }
}

生产者:

public class Produce implements Runnable {
    private OrderPool orderPool;

    public Produce() {
    }

    public Produce(OrderPool orderPool) {
        this.orderPool = orderPool;
    }

    @Override
    public void run() {
        while (true) {
            orderPool.produceOrder();
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值