功能简介:
  • 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);
}
       可以重点关注下put和take方法的行为。
  • 接下来看下ArrayBlockingQueue内部的数据结构:
       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的更多相关文章

  1. Jdk1.6 JUC源码解析(13)-LinkedBlockingQueue

    功能简介: LinkedBlockingQueue是一种基于单向链表实现的有界的(可选的,不指定默认int最大值)阻塞队列.队列中的元素遵循先入先出 (FIFO)的规则.新元素插入到队列的尾部,从队列 ...

  2. Jdk1.6 JUC源码解析(6)-locks-AbstractQueuedSynchronizer

    功能简介: AbstractQueuedSynchronizer(以下简称AQS)是Java并发包提供的一个同步基础机制,是并发包中实现Lock和其他同步机制(如:Semaphore.CountDow ...

  3. Jdk1.6 JUC源码解析(7)-locks-ReentrantLock

    功能简介: Java代码层面提供的锁机制,可做为Synchronized(jvm内置)的替代物,和Synchronized一样都是可重入的. 与Synchronized相比较而言,ReentrantL ...

  4. Jdk1.6 JUC源码解析(1)-atomic-AtomicXXX

    转自:http://brokendreams.iteye.com/blog/2250109 功能简介: 原子量和普通变量相比,主要体现在读写的线程安全上.对原子量的是原子的(比如多线程下的共享变量i+ ...

  5. 【JUC源码解析】ScheduledThreadPoolExecutor

    简介 它是一个线程池执行器(ThreadPoolExecutor),在给定的延迟(delay)后执行.在多线程或者对灵活性有要求的环境下,要优于java.util.Timer. 提交的任务在执行之前支 ...

  6. 【JUC源码解析】Exchanger

    简介 Exchanger,并发工具类,用于线程间的数据交换. 使用 两个线程,两个缓冲区,一个线程往一个缓冲区里面填数据,另一个线程从另一个缓冲区里面取数据.当填数据的线程将缓冲区填满时,或者取数据的 ...

  7. 【JUC源码解析】SynchronousQueue

    简介 SynchronousQueue是一种特殊的阻塞队列,该队列没有容量. [存数据线程]到达队列后,若发现没有[取数据线程]在此等待,则[存数据线程]便入队等待,直到有[取数据线程]来取数据,并释 ...

  8. 【JUC源码解析】ForkJoinPool

    简介 ForkJoin 框架,另一种风格的线程池(相比于ThreadPoolExecutor),采用分治算法,工作密取策略,极大地提高了并行性.对于那种大任务分割小任务的场景(分治)尤其有用. 框架图 ...

  9. 【JUC源码解析】DelayQueue

    简介 基于优先级队列,以过期时间作为排序的基准,剩余时间最少的元素排在队首.只有过期的元素才能出队,在此之前,线程等待. 源码解析 属性 private final transient Reentra ...

随机推荐

  1. dellR720重启找不到启动引导项,手动选择也无用。

    机器重启后显示 no boot device available.(如下图)检查bios中设置也是没问题的,因为装完系统后根本没动过什么.F11手动选择启动项也还是会跳到这里来. 这台机子做的Raid ...

  2. Openstack新建云主机的流程

    前言 前天晚上没睡觉,所以昨天睡得很早,导致今天4点就起来了 时间是人最宝贵的财富,于是我打消了钻在被子里刷剧的念头,爬起来整理一下在Openstack中新建一个云主机的流程. Openstack可以 ...

  3. Windows运行命令大全

    inetmgr   启动IIS控制台winver 检查Windows版本 wmimgmt.msc 打开Windows管理体系结构(wmi) wupdmgr Windows更新程序 wscript Wi ...

  4. XJOI1424解压字符串

    解压字符串 给你一个字符串S,S是已经被加密过的字符串.现在要求你把字符串S还原.字符串S可能会出现这样的格式:k(q),它表示字符串q重复了k次,其中q是0个或多个字符,而k是一个数字,范围是0至9 ...

  5. poptest老李谈分布式与集群

    poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:908821478,咨询电话010-845052 ...

  6. vuejs学习笔记(2)--属性,事件绑定,ajax

    属性 v-for 类似于angular中的 ng-repeat ,用于重复生成html片段: <ul id="box"> <li v-for="(v, ...

  7. Linux之shell编程条件判断-if,while,for,case

    if 语法格式 if condition then statements [elif condition then statements] [else statements ] fi 示例 vi if ...

  8. 浅析 Jndi / DataSource / ConnectionPool 三者

    最近有个用户量 5W-10W 的 web 应用,频繁导致 weblogic 崩溃,让运维组很难受. 通过几天跟踪系统日志和 weblogic 运行状况,发现报错的姿势有很多,其中对定位问题比较关键的报 ...

  9. JavaEE开发之SpringMVC中的自定义拦截器及异常处理

    上篇博客我们聊了<JavaEE开发之SpringMVC中的路由配置及参数传递详解>,本篇博客我们就聊一下自定义拦截器的实现.以及使用ModelAndView对象将Controller的值加 ...

  10. Vuex(二)——关于store

    一.总览 Vuex 应用的核心就是 store(仓库). "store" 包含着应用中大部分的状态(state). 二.Vuex 和单纯全局对象的不同 Vuex 的状态存储是响应式 ...