⑴背景

阻塞队列常用于生产者消费者场景,生产者是向队列里添加元素的线程,消费者是向队列里取出元素的线程。阻塞队列的角色是供生产者存放元素,消费者取出元素的容器。

⑵阻塞队列

阻塞队列是一个支持两个附加操作的队列。(支持阻塞插入和移除方法)

①阻塞插入:当队列满时,队列会阻塞插入元素的线程,直到队列不满。

②阻塞移除:当队列空时,获取元素的线程会等待队列变为空。

  /** The queued items */
     final Object[] items;

     /** items index for next take, poll, peek or remove */
     int takeIndex;

     /** items index for next put, offer, or add */
     int putIndex;

     /** Number of elements in the queue */
     int count;

     /*
      * Concurrency control uses the classic two-condition algorithm
      * found in any textbook.
      */

     /** Main lock guarding all access */
     final ReentrantLock lock;

     /** Condition for waiting takes */
     private final Condition notEmpty;

     /** Condition for waiting puts */
     private final Condition notFull;
 /**
      * Creates an {@code ArrayBlockingQueue} with the given (fixed)
      * capacity and the specified access policy.
      *
      * @param capacity the capacity of this queue
      * @param fair if {@code true} then queue accesses for threads blocked
      *        on insertion or removal, are processed in FIFO order;
      *        if {@code false} the access order is unspecified.
      * @throws IllegalArgumentException if {@code capacity < 1}
      */
     public ArrayBlockingQueue(int capacity, boolean fair) {           //当队列容量小于等于0,会抛异常。当队列满时再继续插入,也会抛该异常
         if (capacity <= 0)
             throw new IllegalArgumentException();           //创建容量数组
         this.items = new Object[capacity];           //创建可重入锁与阻塞条件
         lock = new ReentrantLock(fair);
         notEmpty = lock.newCondition();
         notFull =  lock.newCondition();
     }
 /**
      * Inserts the specified element at the tail of this queue, waiting
      * for space to become available if the queue is full.
      *
      * @throws InterruptedException {@inheritDoc}
      * @throws NullPointerException {@inheritDoc}
      */
     public void put(E e) throws InterruptedException {
         checkNotNull(e);
         final ReentrantLock lock = this.lock;           //lockInterruptibly()允许在等待时由其他线程的Thread.interrupt()方法来中断等待线程而直接返回,这时是不用获取锁的,而会抛出一个InterruptException。           //而ReentrantLock.lock()方法则不允许Thread.interrupt()中断,即使检测到了Thread.interruptted一样会继续尝试获取锁,失败则继续休眠。只是在最后获取锁成功之后在把当前线程置为interrupted状态。
         lock.lockInterruptibly();
         try {               //当队列满时,阻塞插入队列的线程
             while (count == items.length)
                 notFull.await();               //对列不满就入队列
             enqueue(e);
         } finally {               //最后必须释放锁资源
             lock.unlock();
         }
     }
 public E take() throws InterruptedException {
         final ReentrantLock lock = this.lock;           //加锁保证只有一个线程进入take方法
         lock.lockInterruptibly();
         try {               //当队列为空时,阻塞取出元素的线程
             while (count == 0)
                 notEmpty.await();               //当队列队列非空时,允许元素加入队列
             return dequeue();
         } finally {
             lock.unlock();
         }
     }
 /**
      * Inserts element at current put position, advances, and signals.
      * Call only when holding lock.
      */
     private void enqueue(E x) {
         // assert lock.getHoldCount() == 1;
         // assert items[putIndex] == null;
         final Object[] items = this.items;  //确保所有元素只放进同一个数组中
         items[putIndex] = x;
         if (++putIndex == items.length)  //当索引等于数组最大值时,索引置0
             putIndex = 0;
         count++;
         notEmpty.signal();  //使用条件对象notEmpty通知,当调用take,poll,remove时,线程被阻塞,对列为空,当调用enqueue时,队列不为空了,使用signal函数进行通知
     }
 /**
      * Extracts element at current take position, advances, and signals.
      * Call only when holding lock.
      */
     private E dequeue() {
         // assert lock.getHoldCount() == 1;
         // assert items[takeIndex] != null;
         final Object[] items = this.items;
         @SuppressWarnings("unchecked")
         E x = (E) items[takeIndex];
         items[takeIndex] = null;
         if (++takeIndex == items.length)
             takeIndex = 0;
         count--;
         if (itrs != null)
             itrs.elementDequeued();
         notFull.signal();
         return x;
     }

该博客更详细,向博主学习,以后更深入学习后再来完善这篇博客。http://blog.csdn.net/x_i_y_u_e/article/details/52513038

Java源码之阻塞队列的更多相关文章

  1. 【Java源码】集合类-队列Queue

    一.描述 队列Queue这种数据结构,通常指先进先出(FIFO)这种容器.可以模拟生活中依次排队这种场景. 下面是集合体系继承树: 二.Queue Queue和List一样都是Collection的子 ...

  2. Java并发编程:阻塞队列(转载)

    Java并发编程:阻塞队列 在前面几篇文章中,我们讨论了同步容器(Hashtable.Vector),也讨论了并发容器(ConcurrentHashMap.CopyOnWriteArrayList), ...

  3. 12、Java并发编程:阻塞队列

    Java并发编程:阻塞队列 在前面几篇文章中,我们讨论了同步容器(Hashtable.Vector),也讨论了并发容器(ConcurrentHashMap.CopyOnWriteArrayList), ...

  4. (转)Java并发编程:阻塞队列

    Java并发编程:阻塞队列 在前面几篇文章中,我们讨论了同步容器(Hashtable.Vector),也讨论了并发容器(ConcurrentHashMap.CopyOnWriteArrayList), ...

  5. 用Java如何设计一个阻塞队列,然后说说ArrayBlockingQueue和LinkedBlockingQueue

    前言 用Java如何设计一个阻塞队列,这个问题是在面滴滴的时候被问到的.当时确实没回答好,只是说了用个List,然后消费者再用个死循环一直去监控list的是否有值,有值的话就处理List里面的内容.回 ...

  6. 【转】Java并发编程:阻塞队列

    在前面几篇文章中,我们讨论了同步容器(Hashtable.Vector),也讨论了并发容器(ConcurrentHashMap.CopyOnWriteArrayList),这些工具都为我们编写多线程程 ...

  7. Java源码系列1——ArrayList

    本文简单介绍了 ArrayList,并对扩容,添加,删除操作的源代码做分析.能力有限,欢迎指正. ArrayList是什么? ArrayList 就是数组列表,主要用来装载数据.底层实现是数组 Obj ...

  8. 【笔记0-开篇】面试官系统精讲Java源码及大厂真题

    背景 开始阅读 Java 源码的契机,还是在第一年换工作的时候,被大厂的技术面虐的体无完肤,后来总结大厂的面试套路,发现很喜欢问 Java 底层实现,即 Java 源码,于是我花了半年时间,啃下了 J ...

  9. [源码解析] 消息队列 Kombu 之 基本架构

    [源码解析] 消息队列 Kombu 之 基本架构 目录 [源码解析] 消息队列 Kombu 之 基本架构 0x00 摘要 0x01 AMQP 1.1 基本概念 1.2 工作过程 0x02 Poll系列 ...

随机推荐

  1. 数据结构-双向链表(Python实现)

    数据结构在编程世界中一直是非常重要的一环,不管是开发还是算法,哪怕是单纯为了面试,数据结构都是必修课,今天我们介绍链表中的一种--双向链表的代码实现. 好了,话不多说直接上代码. 双向链表 首先,我们 ...

  2. 构建工具--glup如何压缩,丑化代码

    目录 为什么使用 实现 为什么使用 最近在迭代公司的项目,发现项目有如下缺点: 代码没有压缩,js文件,内存大,放在服务器上占空间: 源代码没有混淆或者丑化处理,本公司的程序员写出来的代码和高质量逻辑 ...

  3. Spring Boot微服务电商项目开发实战 --- 多环境部署配置、端口号统一配置及Dubbo提供者消费者实现

    昨天已经搭建好了SpringBoot基于Maven的基础父子级项目,今天开始进入项目分模块及分布式实现.首先我们基于昨天的项目,在父级工程下建lyn-sys,lyn-customer,lyn-good ...

  4. JavaScript入门小案例

    笔记: <!-- JavaScript的特点: 1.基于对象和事件驱动 JavaScript把HTML页面中的每一个元素都当做一个对象来处理,并且这些对象都具有层次关系, 像一颗倒立的树,这种关 ...

  5. Unable to start services through AMBARI UI

    ambari开启nodemanager卡住,后台日志: Mar ::, WARN [ambari-action-scheduler] ActionScheduler: - Exception rece ...

  6. [原创]Zabbix3.4_API的python示例

    说明: 1.python版本为:python2.7 2.zabbix版本为:zabbix3.4 3.通过python脚本调用zabbix的api接口可以实现批量增删改查主机的信息. 示例如下: #-* ...

  7. Python解释器安装教程以及环境变量配置 以及 pycharm的安装与激活

    计算机的组成 主板:人的骨架,用于拓展设备 CPU:人的大脑,用于计算和逻辑处理 硬盘:存储数据(永久储存),比如电脑上的 C盘,D盘 内存:临时记忆(断电即消失) 操作系统:XP win7 win1 ...

  8. 字符串如何实现反转?python实现

    今天和一个同事出去吃饭,突然话风转变,考了问我一个问题,他说哥,你知道字符串怎么反转吗? 我想了想,我擦,回家看我博客.作为一个资深开发,怎么可能被一个毛头小子问住了! 于是,我今天就稍微的整理了一下 ...

  9. git的使用之eclipse Hbuilder

    工欲善其事,必先利其器 eclipse使用git管理项目 准备 eclipse 码云(github)账号 下载插件 首先电脑已经安装好git了,然后在eclipse中下载git的插件. 打开eclip ...

  10. <<Modern CMake>> 翻译 1. CMake 介绍

    <<Modern CMake>> 翻译 1. CMake 介绍 人们喜欢讨厌构建系统. 仅仅观看 CppCon17 上的演讲,就可以看到开发人员因为构建系统而闹笑话的例子. 这 ...