java并发编程-有界阻塞队列ArrayBlockingQueue

ArrayBlockingQueue是Java中的一个有界阻塞队列,其容量在创建时设定。当队列满时,生产者会被阻塞,直到消费者消费;反之,当队列空时,消费者会被阻塞,直到生产者添加新元素。队列的阻塞通过ReentrantLock和条件锁(notFull和notEmpty)实现,保证了线程安全和同步。
摘要由CSDN通过智能技术生成

初识队列

队列大家都知道,大致如下图所示,那么为什么叫阻塞队列呢
举个例子,有一家商店,从工厂进货,顾客从商店买货,那么工厂就是生产者,顾客就是消费者
如果,商店没货了,顾客就需要在商店等着,这就阻塞住了
另一种情况,如果工厂生产的东西太多了,商店放不下了,工厂就得等商店的东西卖一卖再放,这也就会阻塞住
阻塞其实就是队列的一个特性
队列模型

java中Queue家族

从下图可以看出,java中队列家族有这么庞大,我们看介绍按需选用就行了

队列家族

ArrayBlockingQueue

这个队列被成为有界队列,那么为什么被称为有界队列呢,因为它的队列中必须传入一个capacity,也就是队列的容量
并且如果消费不及时,造成队列满的话,会被阻塞,
如果用错api的话,会抛出异常,或者入队不成功,造成消息丢失

条件锁

  1. 如果在商店满了的情况下,商店会通知工厂,队列满了,先不要送货了
  2. 在商店空了的情况下,会通知顾客,先等会,然后通知工厂,可以送货了
  3. 而一旦商店有货了,就会通知顾客来购买
    以上就是条件锁的逻辑,但是在队列里面要简单一点
    消费者消费不到消息了,就会阻塞等待,一旦生产者有消息了,就会通知消费者消费
    一旦队列中满了,生产者会阻塞等待,一旦队列中有坑儿时,就会通知生产者进行入队

条件锁的实现

java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject
条件锁的实现为上边这个类,也是AQS下的
条件锁其实是AQS提供的一个特殊锁,允许用户在任意地方阻塞,在任意地方解阻塞
用户只需根据自己的条件去判断使用,所以它才叫条件锁

ArrayBlockingQueue解析

我们从API追溯源码来看这个队列的实现

构造方法

//capacity 队列初始容量
public ArrayBlockingQueue(int capacity)
//fair为队列中的锁的种类,公平锁或者非公平锁
public ArrayBlockingQueue(int capacity, boolean fair)
//collection为队列初始值,但是不能为空,否则会抛异常
public ArrayBlockingQueue(int capacity, boolean fair,Collection<? extends E> c)

入队

阻塞方法**put(E e)**的实现

public void put(E e) throws InterruptedException {
    checkNotNull(e);
    final ReentrantLock lock = this.lock;
    //此处是对inerrupt信号的校验,如果程序调用了Thread.interrept()方法,就会抛异常
    //否则,会正常加锁
    lock.lockInterruptibly();
    try {
        while (count == items.length)
        	//notFull为条件锁,如果队列中放满了,则会阻塞等待,如果消费者取了一条数据了,才会被唤醒
            notFull.await();
        //入队操作
        enqueue(e);
    } finally {
        lock.unlock();
    }
}

出队/消费

public E take() throws InterruptedException {
	//此处是对inerrupt信号的校验,如果程序调用了Thread.interrept()方法,就会抛异常
    //否则,会正常加锁
    final ReentrantLock lock = this.lock;
    lock.lockInterruptibly();
    try {
        while (count == 0)
        	//notEmpty为条件锁,如果队列中位空时,会触发阻塞等待,等到队列中有值时,才会被解阻塞
            notEmpty.await();
        //出队操作
        return dequeue();
    } finally {
        lock.unlock();
    }
}

图解

正常队列

正常队列

消费不及时

消费不及时会导致队列满了,就会进行阻塞
消费者每消费一个消息,就会发送notFull信号,去唤醒生产者
消费不及时

生产不及时

生产不及时会导致消息队列为空,消费者就会阻塞
每当生产者放一个消息时,就会发送notEmpty信号解阻塞消费者
生产不及时

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值