ArrayBlockingQueue源码分析

1.很久没写博客了,原因是重新找了份电商后台工作。今天来简单解析下JDK的ArrayBlockingQueue阻塞循环队列。

首先我们来看下ArrayBlockingQueue的成员变量

    /**底层的 队列数组*/
    final Object[] items;
    /**读取元素时的下标*/
    int takeIndex;
    /**添加元素时 的 下标*/
    int putIndex;
    /**队列中元素个数*/
    int count;
    final ReentrantLock lock;
    private final Condition notEmpty;
    private final Condition notFull;

构造函数

    public ArrayBlockingQueue(int capacity) {
        this(capacity, false);
    }
    public ArrayBlockingQueue(int capacity, boolean fair) {
        if (capacity <= 0)
            throw new IllegalArgumentException();
        this.items = new Object[capacity];
        lock = new ReentrantLock(fair);
        notEmpty = lock.newCondition();
        notFull =  lock.newCondition();
    }

take(出队)方法

  public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        /* lockInterruptibly: 尝试获取锁,如果锁正在被其它线程占用,则阻塞, 直到其它线程调用此线程的interrupt()方法,将抛出IterruptException
         */
        lock.lockInterruptibly();
        try {
        /*
		          如果此时队列中的元素个数为0,那么就让当前线程wait,并且释放锁。注意:这里使用了while进行重复检查,是为了防止当前线程可能由于  其他未知的原因被唤醒。
        */    
        while (count == 0)
                notEmpty.await();
            //如果队列不为空,则从队列的头部取元素
            return extract();
        } finally {
             //完成锁的释放
            lock.unlock();
        }
    }

extract方法

private E extract() {
        final Object[] items = this.items;
        E x = (E) items[takeIndex];//根据takeIndex来获取当前的元素
        items[takeIndex] = null;
        takeIndex = inc(takeIndex); // takeIndex加1 ,如果takeIndex等于队列最大则置为0
        --count; // 队列元素减1
        notFull.signal(); // 通知其它 生产者线程
        return x;
    }

inc方法

final int inc(int i) {
    	 //当takeIndex的值等于数组的长度时,就会重新置为0,这个一个循环递增的过程,这里看出ArrayBlockingQueue其实是一个循环队列
        return (++i == items.length) ? 0 : i;
    }

put方法

    public void put(E e) throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == items.length) // 队列满了
                notFull.await(); // 当前线程等待
            insert(e);
        } finally {
            lock.unlock();
        }
    }

insert方法

 private void insert(E x) {
        //将当前元素设置到putIndex位置   
        items[putIndex] = x;
        //让putIndex++
        putIndex = inc(putIndex);
        //将队列的大小加1
        ++count;
        //唤醒其他正在处于等待状态的线程
        notEmpty.signal();
    }

重点就是这些,就是利用jdk1.5的condition和Lock实现的生产者消费者队列。

老生常谈:深圳有爱好音乐的会打鼓(吉他,键盘,贝斯等)的程序员和其它职业可以一起交流加入我们乐队一起嗨。我的QQ:657455400

强烈推荐一套Java进阶博客,都是干货,走向架构师不是梦!

Java进阶全套博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值