生产者与消费者,多线程

在实现一个的生产者和消费者(以下简称PC问题(producer-consumer))。遇到了一些问题;

在实现中使用ArrayBlockingQueue,这是一个有最大容量的阻塞队列,在队列中添加元素有3种方式,我想使用put方法,这样不用判断是否队列已经满了,同样取元素使用take,不用判断队列是否为空。

public class Producer implements Runnable {
    Random random = new Random();
    @Override
    public void run() {
        while(true){
            try {
                //模拟生产的时间
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
                    int id = TestSolution.GoodId.incrementAndGet();
                    int s = random.nextInt(TestSolution.goodsName.length);
                    Good good = new Good(id, TestSolution.goodsName[s]);
                    try {
                        TestSolution.goods.put(good);
                        System.out.println(Thread.currentThread().getName() + "  生产了 " + good.toString() + "----已经有产品个数" + TestSolution.goods.size());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                   // TestSolution.goods.notify();
                   //运行上面的会报错
        }
    }
}
public class Consumer implements Runnable  {
    @Override
    public void run() {
        try {
            _run();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    private void _run() throws InterruptedException{
        while (true) {
           //模拟消费的时间
            Thread.sleep(1500);
            {
                Good good = TestSolution.goods.take();
                System.out.println(Thread.currentThread().getName() +
                        "  消费了 " + good.toString() + "----还有剩余产品个数" + TestSolution.goods.size());
            }
            //TestSolution.goods.notify();
            //运行上面的会报错
        }
    }
}
public class TestSolution {
    public static final int MaxSizeOfGoods = 10;
    public static final int ProducerNum =3;
    public static final int ConsumerNum =3;
    public static AtomicInteger GoodId = new AtomicInteger(0);
    public static ArrayBlockingQueue<Good> goods= new ArrayBlockingQueue<>(10);
    public static String goodsName[]= {"娃哈哈", "可口可乐","雪碧","啤酒"};

    public static void main(String[] args) {
        for(int i=0;i<ProducerNum;i++){
            Thread thread = new Thread(new Producer(),"生产者"+(i+1));
            thread.start();
        }
        for(int i=0;i<ConsumerNum;i++){
            Thread thread = new Thread(new Consumer(),"消费者"+(i+1));
            thread.start();
        }
        try {
            TimeUnit.SECONDS.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

 上面的代码主要体现了一个问题,在线程处理过程中不需要显式加锁,但是注意下面的结果;

可以看到由于没有对阻塞队列对象加锁,所以 在打印队列中元素的个数时候会出现问题。但是如果我们只需要PC,不需要阻塞队列对象的信息,那么是可以接受的。

如果一定要阻塞队列的信息准确也很好办,只需要对阻塞队列(goods)进行加锁就行,不需要notify。

 

通过这个代码,我们可以看到put在队列满的时候,会自动释放锁,进入阻塞状态,而唤醒(notify)也不需要我们主动关心。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值