当前位置:首页 > 开发 > 编程语言 > 编程 > 正文

读源码之:ArrayBlockingQueue

发表于: 2014-09-26   作者:dieslrae   来源:转载   浏览:
摘要:     ArrayBlockingQueue是concurrent包提供的一个线程安全的队列,由一个数组来保存队列元素.通过 takeIndex和 putIndex来分别记录出队列和入队列的下标,以保证在出队列时 不进行元素移动. //在出队列或者入队列的时候对takeIndex或者putIndex进行累加,如果已经到了数组末尾就又从0开始,保证数
    ArrayBlockingQueue是concurrent包提供的一个线程安全的队列,由一个数组来保存队列元素.通过 takeIndexputIndex来分别记录出队列和入队列的下标,以保证在出队列时 不进行元素移动.

//在出队列或者入队列的时候对takeIndex或者putIndex进行累加,如果已经到了数组末尾就又从0开始,保证数组的循环使用.
final int inc(int i) {
        return (++i == items.length) ? 0 : i;
    }

//入队列操作
private void insert(E x) {
        items[putIndex] = x;
        putIndex = inc(putIndex);
        ++count;
        notEmpty.signal();//唤醒等待的出队线程
    }

//使用offer入队列,如果队列已满就立即返回false
public boolean offer(E e) {
        checkNotNull(e);
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            if (count == items.length)
                return false;
            else {
                insert(e);
                return true;
            }
        } finally {
            lock.unlock();
        }
    }

//使用put入队列的话,如果队列已满当前线程就等待然后释放锁,直到被notFull唤醒,再重新检查,直到成功插入队列
public void put(E e) throws InterruptedException {
        checkNotNull(e);
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == items.length)
                notFull.await();
            insert(e);
        } finally {
            lock.unlock();
        }
    }

//出队列操作
private E extract() {
        final Object[] items = this.items;
        E x = this.<E>cast(items[takeIndex]);
        items[takeIndex] = null;
        takeIndex = inc(takeIndex);
        --count;
        notFull.signal();//唤醒等待入队的线程
        return x;
    }

//poll出队是不需要等待的,如果当前队列是空就直接返回null
public E poll() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return (count == 0) ? null : extract();
        } finally {
            lock.unlock();
        }
    }

//take就跟put一样,如果队列是空的就等待直到被notEmpty唤醒
public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == 0)
                notEmpty.await();
            return extract();
        } finally {
            lock.unlock();
        }
    }


最后需要注意的就是带 超时唤醒的是 offerpoll而不是put和take

读源码之:ArrayBlockingQueue

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
注意:在阅读本文之前或在阅读的过程中,需要用到ReentrantLock,内容见《第五章 ReentrantLock源码
注意:在阅读本文之前或在阅读的过程中,需要用到ReentrantLock,内容见《第五章 ReentrantLock源码
RESideMenu是github上比较出名的一个开源库,主要是实现侧滑菜单,现在有三千多个star了。效果如下
读一个开源框架,大家最想学到的就是设计的思想和实现的技巧。最近读jQuery源码,记下我对大师作品
读一个开源框架,大家最想学到的就是设计的思想和实现的技巧。最近读jQuery源码,记下我对大师作品
ArrayBlockingQueue是个有数组支持的有界的阻塞队列。该队列按照先进先出FIFO的原理对元素排序,插
源代码解析 Re'entrantLock lock = new ReentrantLock(fair); Condition notEmpty = <span style
看了下Sizzle部分源码,核心的原理就是使用正则表达式去匹配,找到对应的原生获取元素的方法,我没
首先你得准备一个很简单的struts2的程序,可以发一次请求后能返回一个正确的响应,当然,struts2的
目前只读了BaseObjectPool这部分的源码。下面是pool中几个重要的类,和自己业务类之间的UML关系图。
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号