功能简介:
  • ArrayBlockingQueue是一种基于数组实现的有界的阻塞队列。队列中的元素遵循先入先出(FIFO)的规则。新元素插入到队列的尾部,从队列头部取出元素。
  • 和普通队列有所不同,该队列支持阻塞操作。比如从空队列中取元素,会导致当前线程阻塞,直到其他线程将元素放入队列;将元素插入已经满的队列,同样会导致当前线程阻塞,直到其他线程从队列中取出元素。
  • ArrayBlockingQueue也支持公平和非公平策略(针对队列中元素的存取线程,也可认为是元素的生产者和消费者)。
源码分析:
  • ArrayBlockingQueue继承了AbstractQueue并实现了BlockingQueue,AbstractQueue是Queue的公共骨架实现,这个不看了,简单看下BlockingQueue接口:
  1. public interface BlockingQueue<E> extends Queue<E> {
  2. /**
  3. * 将一个元素放入队列。
  4. * 成功返回true;失败抛IllegalStateException异常。
  5. */
  6. boolean add(E e);
  7. /**
  8. * 将一个元素放入队列。
  9. * 成功返回true;失败返回false。
  10. */
  11. boolean offer(E e);
  12. /**
  13. * 将一个元素放入队列。
  14. * 如果元素无法放入队列,当前操作线程会等待,直到元素可以放入队列。
  15. */
  16. void put(E e) throws InterruptedException;
  17. /**
  18. * 将一个元素放入队列。
  19. * 如果元素无法放入队列,当前操作线程会等待,直到元素可以放入队列或者
  20. * 给定的时间超时。
  21. * 成功返回true;超时返回false;
  22. */
  23. boolean offer(E e, long timeout, TimeUnit unit)
  24. throws InterruptedException;
  25. /**
  26. * 从队列头部获取并删除一个元素。
  27. * 如果无法获取元素,当前操作线程等待,直到有元素可以被获取。
  28. */
  29. E take() throws InterruptedException;
  30. /**
  31. * 从队列头部获取并删除一个元素。
  32. * 如果无法获取元素,当前操作线程等待,直到有元素可以被获取或者给定时间超时。
  33. * 如果超时,返回null。
  34. */
  35. E poll(long timeout, TimeUnit unit)
  36. throws InterruptedException;
  37. /**
  38. * 获取队列剩余容量。
  39. */
  40. int remainingCapacity();
  41. /**
  42. * 移除队列中和给定元素相同的元素。
  43. */
  44. boolean remove(Object o);
  45. /**
  46. * 判断队列中是否包含给定元素。
  47. */
  48. public boolean contains(Object o);
  49. /**
  50. * 移除队列中所有的可用元素,并把它们添加到给定集合。
  51. */
  52. int drainTo(Collection<? super E> c);
  53. /**
  54. * 移除队列中不超过给定数量的可用元素,并把它们添加到给定集合。
  55. */
  56. int drainTo(Collection<? super E> c, int maxElements);
  57. }
       可以重点关注下put和take方法的行为。
  • 接下来看下ArrayBlockingQueue内部的数据结构:
       ArrayBlockingQueue内部结构非常简单,就是一个数组,一把锁,两个条件;也可以看到,上面提到的公平和非公平策略是由内部的重入锁来支持的。
  • 继续看下ArrayBlockingQueue的重要方法,重点看下put和take,先看下put方法:
  1. public void put(E e) throws InterruptedException {
  2. if (e == null) throw new NullPointerException();
  3. final E[] items = this.items;
  4. final ReentrantLock lock = this.lock;
  5. //由于需要支持方法可中断行为,这里使用可中断的锁操作。
  6. lock.lockInterruptibly();
  7. try {
  8. try {
  9. while (count == items.length)
  10. notFull.await();//队列满时,在notFull条件上等待。
  11. } catch (InterruptedException ie) {
  12. notFull.signal(); // 被中断后,唤醒其他等待notFull条件的线程。
  13. throw ie;
  14. }
  15. insert(e);
  16. } finally {
  17. lock.unlock();
  18. }
  19. }
  20.  
  21. /**
  22. * Circularly increment i.
  23. */
  24. final int inc(int i) {
  25. return (++i == items.length)? 0 : i;
  26. }
  27. /**
  28. * 在内部数组的putIndex位置插入元素,调整putIndex和count,然后唤醒notEmpty条件上等待的线程。
  29. * 本方法只有在持有锁的情况下才会被调用。
  30. */
  31. private void insert(E x) {
  32. items[putIndex] = x;
  33. putIndex = inc(putIndex);
  34. ++count;
  35. notEmpty.signal();
  36. }

再看下take方法:

  1. public E take() throws InterruptedException {
  2. final ReentrantLock lock = this.lock;
  3. lock.lockInterruptibly();
  4. try {
  5. try {
  6. while (count == 0)
  7. notEmpty.await();//队列空时,在notEmpty条件上等待。
  8. } catch (InterruptedException ie) {
  9. notEmpty.signal(); // 被中断后,唤醒其他等待notEmpty条件的线程。
  10. throw ie;
  11. }
  12. E x = extract();
  13. return x;
  14. } finally {
  15. lock.unlock();
  16. }
  17. }
  18. /**
  19. * 从takeInde的位置取出元素,增加takeIndex,减少count,唤醒在notFull上等待的线程。
  20. * 本方法只有在持有锁的情况下才会被调用。
  21. */
  22. private E extract() {
  23. final E[] items = this.items;
  24. E x = items[takeIndex];
  25. items[takeIndex] = null;
  26. takeIndex = inc(takeIndex);
  27. --count;
  28. notFull.signal();
  29. return x;
  30. }
  • 其他方法的实现也都比较简单,不进行一一解析。最后注意一下,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. js移动端横竖屏检测

    方法一:用resize事件来判断,利用屏幕的宽高比,来判断横竖屏 (兼容性较好) (function () { var updateOrientation = function () { var or ...

  2. Sublime Text 3常用插件

    操作:按下Ctrl+Shift+P调出命令面板 输入install 调出 Install Package 选项并回车,然后在列表中选中要安装的插件. 常用插件: 1---- Bracket Highl ...

  3. 如何用Android Studio查看build.gradle源码

    上一篇博客里讲过 build.gradle 里的每一行代码基本都是在调用一个方法,既然是这样,我们就可以用 android studio(下面简称as) 去查看它源码的方法注释说明,这样就可以理解每个 ...

  4. 通过哨兵机制实现Redis主从配置以及java调用

    Redis版本:3.0.7 操作环境:Linux 一.redis 主从配置的作用是什么 redis主从配置,配置master 只能为写,slave只能为读,在客户端对poolconnect请求时候,, ...

  5. js两个判断&&的值与||的值

    var value1="val1"; var value2="val2"; alert(value1&&value2);    //结果为val ...

  6. js根据条件json生成随机json:randomjson

    前端开发中,在做前后端分离的时候,经常需要手写json数据,有3个问题特别揪心: 1,数据是写死的,不能按一定的条件随机生成长度不一,内容不一的数据 2,写数组的时候,如果有很多条,需要一条一条地写, ...

  7. Android使用本地广播

    Android本地广播学习中一直被忽略,今天用到了,Mark一下 1.本地广播的定义和普通广播一样 例如 public class WakeTimesBroadcastReceiver extends ...

  8. windows系统System32中各种实用的工具

    工具类 这些工具可以直接打开运行  输入名字就可以调出来了 我还会上传一个java程序,运行后会显示一个界面,直接调用这些工具 1.SnippingTool.exe   截图 2.calc.exe   ...

  9. Nature:新发现挑战神经元作用传统理论 [转自科学网]

    美德科学家独立进行的两项最新研究表明,单个神经元的激发就足以影响学习和行为.这一结论挑战了人们长期以来的认识,即数千个神经元的有序排列才能够产生一个行为反应.这两篇论文12月19日在线发表于<自 ...

  10. .Net 官方学习文档

    .Net 官方学习文档:https://docs.microsoft.com/zh-cn/dotnet/articles/welcome