1.BlockingQueue定义的常用方法如下
  抛出异常 特殊值 阻塞 超时
插入 add(e) offer(e) put(e) offer(e,time,unit)
移除 remove() poll() take() poll(time,unit)
检查 element() peek() 不可用 不可用
 

1)add(anObject):把anObject加到BlockingQueue里,即如果BlockingQueue可以容纳,则返回true,否则招聘异常

2)offer(anObject):表示如果可能的话,将anObject加到BlockingQueue里,即如果BlockingQueue可以容纳,则返回true,否则返回false.

3)put(anObject):把anObject加到BlockingQueue里,如果BlockQueue没有空间,则调用此方法的线程被阻断直到BlockingQueue里面有空间再继续.

4)poll(time):取走BlockingQueue里排在首位的对象,若不能立即取出,则可以等time参数规定的时间,取不到时返回null

5)take():取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态直到Blocking有新的对象被加入为止

其中:BlockingQueue 不接受null 元素。试图addput 或offer 一个null 元素时,某些实现会抛出NullPointerExceptionnull 被用作指示poll 操作失败的警戒值。 
 

2、BlockingQueue的几个注意点

【1】BlockingQueue 可以是限定容量的。它在任意给定时间都可以有一个remainingCapacity,超出此容量,便无法无阻塞地put 附加元素。没有任何内部容量约束的BlockingQueue 总是报告Integer.MAX_VALUE 的剩余容量。

【2】BlockingQueue 实现主要用于生产者-使用者队列,但它另外还支持Collection 接口。因此,举例来说,使用remove(x) 从队列中移除任意一个元素是有可能的。然而,这种操作通常 会有效执行,只能有计划地偶尔使用,比如在取消排队信息时。

【3】BlockingQueue 实现是线程安全的。所有排队方法都可以使用内部锁或其他形式的并发控制来自动达到它们的目的。然而,大量的 Collection 操作(addAllcontainsAllretainAll 和removeAll没有 必要自动执行,除非在实现中特别说明。因此,举例来说,在只添加了c 中的一些元素后,addAll(c) 有可能失败(抛出一个异常)。

【4】BlockingQueue 实质上不支持使用任何一种“close”或“shutdown”操作来指示不再添加任何项。这种功能的需求和使用有依赖于实现的倾向。例如,一种常用的策略是:对于生产者,插入特殊的end-of-stream 或poison 对象,并根据使用者获取这些对象的时间来对它们进行解释。
 
3、简要概述BlockingQueue常用的四个实现类

 

1)ArrayBlockingQueue:规定大小的BlockingQueue,其构造函数必须带一个int参数来指明其大小.其所含的对象是以FIFO(先入先出)顺序排序的.

2)LinkedBlockingQueue:大小不定的BlockingQueue,若其构造函数带一个规定大小的参数,生成的BlockingQueue有大小限制,若不带大小参数,所生成的BlockingQueue的大小由Integer.MAX_VALUE来决定.其所含的对象是以FIFO(先入先出)顺序排序的

3)PriorityBlockingQueue:类似于LinkedBlockQueue,但其所含对象的排序不是FIFO,而是依据对象的自然排序顺序或者是构造函数的Comparator决定的顺序.

4)SynchronousQueue:特殊的BlockingQueue,对其的操作必须是放和取交替完成的.

    
其中LinkedBlockingQueue和ArrayBlockingQueue比较起来,它们背后所用的数据结构不一样,导致LinkedBlockingQueue的数据吞吐量要大于ArrayBlockingQueue,但在线程数量很大时其性能的可预见性低于ArrayBlockingQueue.  
 
下面主要看一下ArrayBlockingQueue的源码:
  1. public boolean offer(E e) {
  2. if (e == null) throw new NullPointerException();
  3. final ReentrantLock lock = this.lock;//每个对象对应一个显示的锁
  4. lock.lock();//请求锁直到获得锁(不可以被interrupte)
  5. try {
  6. if (count == items.length)//如果队列已经满了
  7. return false;
  8. else {
  9. insert(e);
  10. return true;
  11. }
  12. } finally {
  13. lock.unlock();//
  14. }
  15. }
  16. 看insert方法:
  17. private void insert(E x) {
  18. items[putIndex] = x;
  19. //增加全局index的值。
  20. /*
  21. Inc方法体内部:
  22. final int inc(int i) {
  23. return (++i == items.length)? 0 : i;
  24. }
  25. 这里可以看出ArrayBlockingQueue采用从前到后向内部数组插入的方式插入新元素的。如果插完了,putIndex可能重新变为0(在已经执行了移除操作的前提下,否则在之前的判断中队列为满)
  26. */
  27. putIndex = inc(putIndex);
  28. ++count;
  29. notEmpty.signal();//wake up one waiting thread
  30. }
 
  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. lock.lockInterruptibly();//请求锁直到得到锁或者变为interrupted
  6. try {
  7. try {
  8. while (count == items.length)//如果满了,当前线程进入noFull对应的等waiting状态
  9. notFull.await();
  10. } catch (InterruptedException ie) {
  11. notFull.signal(); // propagate to non-interrupted thread
  12. throw ie;
  13. }
  14. insert(e);
  15. } finally {
  16. lock.unlock();
  17. }
  18. }
 
  1. public boolean offer(E e, long timeout, TimeUnit unit)
  2. throws InterruptedException {
  3. if (e == null) throw new NullPointerException();
  4. long nanos = unit.toNanos(timeout);
  5. final ReentrantLock lock = this.lock;
  6. lock.lockInterruptibly();
  7. try {
  8. for (;;) {
  9. if (count != items.length) {
  10. insert(e);
  11. return true;
  12. }
  13. if (nanos <= 0)
  14. return false;
  15. try {
  16. //如果没有被 signal/interruptes,需要等待nanos时间才返回
  17. nanos = notFull.awaitNanos(nanos);
  18. } catch (InterruptedException ie) {
  19. notFull.signal(); // propagate to non-interrupted thread
  20. throw ie;
  21. }
  22. }
  23. } finally {
  24. lock.unlock();
  25. }
  26. }
 
  1. public boolean add(E e) {
  2. return super.add(e);
  3. }
  4. 父类:
  5. public boolean add(E e) {
  6. if (offer(e))
  7. return true;
  8. else
  9. throw new IllegalStateException("Queue full");
  10. }
 
该类中有几个实例变量:takeIndex/putIndex/count
  1. 用三个数字来维护这个队列中的数据变更:
  2. /** items index for next take, poll or remove */
  3. private int takeIndex;
  4. /** items index for next put, offer, or add. */
  5. private int putIndex;
  6. /** Number of items in the queue */
  7. private int count;
 
 
转自:http://blog.csdn.net/vernonzheng/article/details/8247564

BlockingQueue深入分析(转)的更多相关文章

  1. BlockingQueue深入分析

    1.BlockingQueue定义的常用方法如下   抛出异常 特殊值 阻塞 超时 插入 add(e) offer(e) put(e) offer(e,time,unit) 移除 remove() p ...

  2. Java多线程(五)之BlockingQueue深入分析

    一.概述: BlockingQueue作为线程容器,可以为线程同步提供有力的保障.   二.BlockingQueue定义的常用方法 1.BlockingQueue定义的常用方法如下:  1)add( ...

  3. BlockingQueue

    BlockingQueue的使用 http://www.cnblogs.com/liuling/p/2013-8-20-01.html BlockingQueue深入分析 http://blog.cs ...

  4. paip.java 线程无限wait的解决

    paip.java  线程无限wait的解决 jprofl>threads>thread dump> 查看棉线程执行的code stack... 估计是.比如.BlockingQue ...

  5. JDK源码分析—— ArrayBlockingQueue 和 LinkedBlockingQueue

    JDK源码分析—— ArrayBlockingQueue 和 LinkedBlockingQueue 目的:本文通过分析JDK源码来对比ArrayBlockingQueue 和LinkedBlocki ...

  6. 《java并发编程实战》读书笔记4--基础构建模块,java中的同步容器类&并发容器类&同步工具类,消费者模式

    上一章说道委托是创建线程安全类的一个最有效策略,只需让现有的线程安全的类管理所有的状态即可.那么这章便说的是怎么利用java平台类库的并发基础构建模块呢? 5.1 同步容器类 包括Vector和Has ...

  7. 并发编程 20—— AbstractQueuedSynchronizer 深入分析

    Java并发编程实践 目录 并发编程 01—— ThreadLocal 并发编程 02—— ConcurrentHashMap 并发编程 03—— 阻塞队列和生产者-消费者模式 并发编程 04—— 闭 ...

  8. 并发编程 06—— CompletionService :Executor 和 BlockingQueue

    Java并发编程实践 目录 并发编程 01—— ThreadLocal 并发编程 02—— ConcurrentHashMap 并发编程 03—— 阻塞队列和生产者-消费者模式 并发编程 04—— 闭 ...

  9. 3W字干货深入分析基于Micrometer和Prometheus实现度量和监控的方案

    前提 最近线上的项目使用了spring-actuator做度量统计收集,使用Prometheus进行数据收集,Grafana进行数据展示,用于监控生成环境机器的性能指标和业务数据指标.一般,我们叫这样 ...

随机推荐

  1. XML 架构 (XSD) 参考

    https://msdn.microsoft.com/zh-cn/library/ms256235.aspx XML 架构示例 XML 架构元素 XML 数据类型引用 XML 架构正则表达式 XML ...

  2. pycloudtag 标签云

    原创,转载请标明 QQ:231469242 # -*- coding: utf-8 -*- """Python3.0 Created on Sat Nov 26 08:5 ...

  3. php无刷新上传图片和文件

    核心思想:通过Html的iframe标签属性操作顶级窗口,再用php动态无刷新上传图片文件. 示例如下: demo |------uploads #存放上传的文件 |------index.php | ...

  4. context元素大概解说

    Context元素代表一个web应用,运行在某个特定的虚拟主机上.如Servlet Specification 2.2或以后版本中描述的那样,每个web应用基于一个Web Application Ar ...

  5. Python之路【第二十一篇】Django ORM详解

    ORM回顾 关系对象映射(Object Relational Mapping,简称ORM). django中遵循 Code Frist 的原则,即:根据代码中定义的类来自动生成数据库表. 对于ORM框 ...

  6. SQL Server附加数据库时报1813错误的解决方案

    SQL Server附加数据库时报1813错误的解决方案   无法打开新数据库 'ASR'.CREATE DATABASE 中止. 文件激活失败.物理文件名称'E:\SqlServer\MSSQL\D ...

  7. css之div等继承问题--待续

    div哪些属性是可以继承的呢? 亲测:float可以继承(错的,见下解答,),display不可以继承.有待继续学习. float不可以继承, 简单来说:浮动的元素,顾名思义,就是这个元素“浮起来”了 ...

  8. [译]git的那些flag

    git add -p console有一个交互式的界面(如下图),让你一个一个文件的选择是add还是不add.注意这些文件必须是tracked过的, 也就是说如果你的新的文件从来没有add过,那么他不 ...

  9. 【荐】PHP Session和Cookie,Session阻塞,Session垃圾回收,Redis共享Session,不推荐Memcached保存Session

    什么是 Session 在 web 应用开发中,Session 被称为会话.主要被用于保存某个访问者的数据. 由于 HTTP 无状态的特点,服务端是不会记住客户端的,对服务端来说,每一个请求都是全新的 ...

  10. PHP错误处理函数set_error_handler()的用法

    定义和用法 set_error_handler() 函数设置用户自定义的错误处理函数. 该函数用于创建运行时期间的用户自己的错误处理方法. 该函数会返回旧的错误处理程序,若失败,则返回 null. 语 ...