Jdk1.6 JUC源码解析(12)-ArrayBlockingQueue
- ArrayBlockingQueue是一种基于数组实现的有界的阻塞队列。队列中的元素遵循先入先出(FIFO)的规则。新元素插入到队列的尾部,从队列头部取出元素。
- 和普通队列有所不同,该队列支持阻塞操作。比如从空队列中取元素,会导致当前线程阻塞,直到其他线程将元素放入队列;将元素插入已经满的队列,同样会导致当前线程阻塞,直到其他线程从队列中取出元素。
- ArrayBlockingQueue也支持公平和非公平策略(针对队列中元素的存取线程,也可认为是元素的生产者和消费者)。
- ArrayBlockingQueue继承了AbstractQueue并实现了BlockingQueue,AbstractQueue是Queue的公共骨架实现,这个不看了,简单看下BlockingQueue接口:
public interface BlockingQueue<E> extends Queue<E> {
    /**
     * 将一个元素放入队列。
     * 成功返回true;失败抛IllegalStateException异常。
     */
    boolean add(E e);
    /**
     * 将一个元素放入队列。
     * 成功返回true;失败返回false。
     */
    boolean offer(E e);
    /**
     * 将一个元素放入队列。
     * 如果元素无法放入队列,当前操作线程会等待,直到元素可以放入队列。
     */
    void put(E e) throws InterruptedException;
    /**
     * 将一个元素放入队列。
     * 如果元素无法放入队列,当前操作线程会等待,直到元素可以放入队列或者
     * 给定的时间超时。
     * 成功返回true;超时返回false;
     */
    boolean offer(E e, long timeout, TimeUnit unit)
        throws InterruptedException;
    /**
     * 从队列头部获取并删除一个元素。
     * 如果无法获取元素,当前操作线程等待,直到有元素可以被获取。
     */
    E take() throws InterruptedException;
    /**
     * 从队列头部获取并删除一个元素。
     * 如果无法获取元素,当前操作线程等待,直到有元素可以被获取或者给定时间超时。
     * 如果超时,返回null。
     */
    E poll(long timeout, TimeUnit unit)
        throws InterruptedException;
    /**
     * 获取队列剩余容量。
     */
    int remainingCapacity();
    /**
     * 移除队列中和给定元素相同的元素。
     */
    boolean remove(Object o);
    /**
     * 判断队列中是否包含给定元素。
     */
    public boolean contains(Object o);
    /**
     * 移除队列中所有的可用元素,并把它们添加到给定集合。
     */
    int drainTo(Collection<? super E> c);
    /**
     * 移除队列中不超过给定数量的可用元素,并把它们添加到给定集合。
     */
    int drainTo(Collection<? super E> c, int maxElements);
}
- 接下来看下ArrayBlockingQueue内部的数据结构:
- 继续看下ArrayBlockingQueue的重要方法,重点看下put和take,先看下put方法:
    public void put(E e) throws InterruptedException {
        if (e == null) throw new NullPointerException();
        final E[] items = this.items;
        final ReentrantLock lock = this.lock;
        //由于需要支持方法可中断行为,这里使用可中断的锁操作。
        lock.lockInterruptibly();
        try {
            try {
                while (count == items.length)
                    notFull.await();//队列满时,在notFull条件上等待。
            } catch (InterruptedException ie) {
                notFull.signal(); // 被中断后,唤醒其他等待notFull条件的线程。
                throw ie;
            }
            insert(e);
        } finally {
            lock.unlock();
        }
    }
    /**
     * Circularly increment i.
     */
    final int inc(int i) {
        return (++i == items.length)? 0 : i;
    }
    /**
     * 在内部数组的putIndex位置插入元素,调整putIndex和count,然后唤醒notEmpty条件上等待的线程。
     * 本方法只有在持有锁的情况下才会被调用。
     */
    private void insert(E x) {
        items[putIndex] = x;
        putIndex = inc(putIndex);
        ++count;
        notEmpty.signal();
    }
再看下take方法:
    public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            try {
                while (count == 0)
                    notEmpty.await();//队列空时,在notEmpty条件上等待。
            } catch (InterruptedException ie) {
                notEmpty.signal(); // 被中断后,唤醒其他等待notEmpty条件的线程。
                throw ie;
            }
            E x = extract();
            return x;
        } finally {
            lock.unlock();
        }
    }
    /**
     * 从takeInde的位置取出元素,增加takeIndex,减少count,唤醒在notFull上等待的线程。
     * 本方法只有在持有锁的情况下才会被调用。
     */
    private E extract() {
        final E[] items = this.items;
        E x = items[takeIndex];
        items[takeIndex] = null;
        takeIndex = inc(takeIndex);
        --count;
        notFull.signal();
        return x;
    }
- 其他方法的实现也都比较简单,不进行一一解析。最后注意一下,ArrayBlockingQueue的Iterator是弱一致的。
Jdk1.6 JUC源码解析(12)-ArrayBlockingQueue的更多相关文章
- Jdk1.6 JUC源码解析(13)-LinkedBlockingQueue
		功能简介: LinkedBlockingQueue是一种基于单向链表实现的有界的(可选的,不指定默认int最大值)阻塞队列.队列中的元素遵循先入先出 (FIFO)的规则.新元素插入到队列的尾部,从队列 ... 
- Jdk1.6 JUC源码解析(6)-locks-AbstractQueuedSynchronizer
		功能简介: AbstractQueuedSynchronizer(以下简称AQS)是Java并发包提供的一个同步基础机制,是并发包中实现Lock和其他同步机制(如:Semaphore.CountDow ... 
- Jdk1.6 JUC源码解析(7)-locks-ReentrantLock
		功能简介: Java代码层面提供的锁机制,可做为Synchronized(jvm内置)的替代物,和Synchronized一样都是可重入的. 与Synchronized相比较而言,ReentrantL ... 
- Jdk1.6 JUC源码解析(1)-atomic-AtomicXXX
		转自:http://brokendreams.iteye.com/blog/2250109 功能简介: 原子量和普通变量相比,主要体现在读写的线程安全上.对原子量的是原子的(比如多线程下的共享变量i+ ... 
- 【JUC源码解析】ScheduledThreadPoolExecutor
		简介 它是一个线程池执行器(ThreadPoolExecutor),在给定的延迟(delay)后执行.在多线程或者对灵活性有要求的环境下,要优于java.util.Timer. 提交的任务在执行之前支 ... 
- 【JUC源码解析】Exchanger
		简介 Exchanger,并发工具类,用于线程间的数据交换. 使用 两个线程,两个缓冲区,一个线程往一个缓冲区里面填数据,另一个线程从另一个缓冲区里面取数据.当填数据的线程将缓冲区填满时,或者取数据的 ... 
- 【JUC源码解析】SynchronousQueue
		简介 SynchronousQueue是一种特殊的阻塞队列,该队列没有容量. [存数据线程]到达队列后,若发现没有[取数据线程]在此等待,则[存数据线程]便入队等待,直到有[取数据线程]来取数据,并释 ... 
- 【JUC源码解析】ForkJoinPool
		简介 ForkJoin 框架,另一种风格的线程池(相比于ThreadPoolExecutor),采用分治算法,工作密取策略,极大地提高了并行性.对于那种大任务分割小任务的场景(分治)尤其有用. 框架图 ... 
- 【JUC源码解析】DelayQueue
		简介 基于优先级队列,以过期时间作为排序的基准,剩余时间最少的元素排在队首.只有过期的元素才能出队,在此之前,线程等待. 源码解析 属性 private final transient Reentra ... 
随机推荐
- require.js 源码解读——配置默认上下文
			首先,我们先来简单说一下,require.js的原理: 1.载入模块 2.通过模块名解析出模块信息,以及计算出URL 3.通过创建SCRIPT的形式把模块加载到页面中. 4.判断被加载的脚本,如 ... 
- Jquery EasyUI远程校验,Jquery EasyUI多个自定义校验,EasyUI自定义校验
			>>>>>>>>>>>>>>>>>>>>>>>>> ... 
- PMBOK 和 PRINCE2的技术不同的地方是什么
			首先,PMBOK是一个框架指导,PRINCE2是一种实现方法. PMBOK是一种建议及最佳实践的集锦.PMBOK包含项目管理的工具和技术并且是一个指导,告诉我们如何做事情,在一种环境中怎样处理问题;而 ... 
- mybatis generator 插件安装及使用
			现在Mybatis特别火,但是在开发中却要经常写实体类和配置文件,会不会特别烦人,所以可以利用Mybatis的代码生成插件来生成这部分代码: 1,打开eclipse,点击Help>Softwar ... 
- CF615D Multipliers [数学]
			tags:[计数原理][乘法逆元][归纳の思想]题解(复杂度:O(mlogm)):棘手之处:n的约数多到爆炸.因此我们不妨从因子的角度来分析问题.对n分解质因数得:n = p1^a1 * p2^a2 ... 
- 持续集成:TestNG中case之间的关系
			持续集成:TestNG中case之间的关系 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq: ... 
- 性能测试分享: Jmeter的源码分析main函数参数
			性能测试分享: Jmeter的源码分析main函数参数 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大 ... 
- 大数据测试之hadoop系统生态
			poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标,也是国内最早探索大数据测试培训的机构,开发了独有的课程体系.如果对课程感兴趣,请大 ... 
- 解决eclipse中文字很小
			新下载的eclipse4.2.1版本,显示中文字体很小,但是英文比较正常.网上查看要更改字体大小,但是更改后英文也变大了,不是想要的结果. window – preferences – general ... 
- Git基本操作命令
			先配置用户和邮箱: Administrator@USER-20150302NL MINGW32 ~$ git config --global user.name "youname" ... 
