想必大家都很熟悉生产者-消费者队列,生产者负责添加元素到队列,如果队列已满则会进入阻塞状态直到有消费者拿走元素。相反,消费者负责从队列中拿走元素,如果队列为空则会进入阻塞状态直到有生产者添加元素到队列。BlockingQueue就是这么一个生产者-消费者队列。

BlockingQueue是Queue的子接口

public interface BlockingQueue<E> extends Queue<E>

BlockingQueue拿走元素时,如果队列为空,阻塞等待会有两种情况:

一种是一直等待直到队列不为空,这种情况调用take方法

E take() throws InterruptedException;

另一种就是设定一个超时时间,一直等到超时,这种情况调用的是pool方法

E poll(long timeout, TimeUnit unit) throws InterruptedException;

同样对于添加元素来说,也有两种情况:

一直等待使用put方法

void put(E e) throws InterruptedException;

超时等待使用offer方法

boolean offer(E e, long timeout, TimeUnit unit)
throws InterruptedException;

BlockingQueue的父接口Queue关于拿走元素的接口有两个:remove和pool。

两者的区别在于当队列为空时前者会抛出NoSuchElementException,而后者返回null。

E remove();
E poll();

添加元素的接口也有两个:add和offer。两者的区别在于当队列为满时前者会抛出IllegalStateException,而后者返回false。

boolean add(E e);
boolean offer(E e);

一般来说Queue类型的数据结构会有两种实现:数组和链表。对应到BlockingQueue就是ArrayBlockingQueue和LinkedBlockingQueue,两者都是基于AbstractQueue实现的。

public class ArrayBlockingQueue<E> extends AbstractQueue<E>
implements BlockingQueue<E>, java.io.Serializable
public class LinkedBlockingQueue<E> extends AbstractQueue<E>
implements BlockingQueue<E>, java.io.Serializable

这里很有必要说说AbstractQueue,AbstractQueue只是实现了add和remove方法,而且很有意思的是这两个方法都是借助他们对应的无异常版本的方法offer和pool来实现的。

    public boolean add(E e) {
if (offer(e))
return true;
else
throw new IllegalStateException("Queue full");
}
    public E remove() {
E x = poll();
if (x != null)
return x;
else
throw new NoSuchElementException();
}

这样做的好处无疑是提供了良好的扩展性,也就是把真正添加/拿走元素的实现留给子类来完成(可以实现线程安全和非线程安全两个版本)。

研究BlockingQueue关注的重点就是Blocking是如果实现的,接下来的两篇文章将会详细分析ArrayBlockingQueue和LinkedBlockingQueue如何实现线程的Blocking。

《java.util.concurrent 包源码阅读》05 BlockingQueue的更多相关文章

  1. 《java.util.concurrent 包源码阅读》 结束语

    <java.util.concurrent 包源码阅读>系列文章已经全部写完了.开始的几篇文章是根据自己的读书笔记整理出来的(当时只阅读了部分的源代码),后面的大部分都是一边读源代码,一边 ...

  2. 《java.util.concurrent 包源码阅读》13 线程池系列之ThreadPoolExecutor 第三部分

    这一部分来说说线程池如何进行状态控制,即线程池的开启和关闭. 先来说说线程池的开启,这部分来看ThreadPoolExecutor构造方法: public ThreadPoolExecutor(int ...

  3. 《java.util.concurrent 包源码阅读》02 关于java.util.concurrent.atomic包

    Aomic数据类型有四种类型:AomicBoolean, AomicInteger, AomicLong, 和AomicReferrence(针对Object的)以及它们的数组类型, 还有一个特殊的A ...

  4. 《java.util.concurrent 包源码阅读》04 ConcurrentMap

    Java集合框架中的Map类型的数据结构是非线程安全,在多线程环境中使用时需要手动进行线程同步.因此在java.util.concurrent包中提供了一个线程安全版本的Map类型数据结构:Concu ...

  5. 《java.util.concurrent 包源码阅读》17 信号量 Semaphore

    学过操作系统的朋友都知道信号量,在java.util.concurrent包中也有一个关于信号量的实现:Semaphore. 从代码实现的角度来说,信号量与锁很类似,可以看成是一个有限的共享锁,即只能 ...

  6. 《java.util.concurrent 包源码阅读》06 ArrayBlockingQueue

    对于BlockingQueue的具体实现,主要关注的有两点:线程安全的实现和阻塞操作的实现.所以分析ArrayBlockingQueue也是基于这两点. 对于线程安全来说,所有的添加元素的方法和拿走元 ...

  7. 《java.util.concurrent 包源码阅读》09 线程池系列之介绍篇

    concurrent包中Executor接口的主要类的关系图如下: Executor接口非常单一,就是执行一个Runnable的命令. public interface Executor { void ...

  8. 《java.util.concurrent 包源码阅读》10 线程池系列之AbstractExecutorService

    AbstractExecutorService对ExecutorService的执行任务类型的方法提供了一个默认实现.这些方法包括submit,invokeAny和InvokeAll. 注意的是来自E ...

  9. 《java.util.concurrent 包源码阅读》22 Fork/Join框架的初体验

    JDK7引入了Fork/Join框架,所谓Fork/Join框架,个人解释:Fork分解任务成独立的子任务,用多线程去执行这些子任务,Join合并子任务的结果.这样就能使用多线程的方式来执行一个任务. ...

随机推荐

  1. MySQL中字段类型为timestamp的小坑

    之前遇到过一个MySQL的字段为timestamp类型的小坑. MySQL中一个字段存储时间类型数据的时候,该字段的类型如果为timestamp类型的话,最多只能存储到2038-01-19 11:14 ...

  2. QT多标签浏览器(一)

    最近在用QT写个简单的浏览器,原来的版本是5.7,没有QWebView,而是使用QAxWidget加载ie.优点是打开网页速度快,但是当点击网页中的链接时,会自动调用windows的IE浏览器,水平有 ...

  3. .net 面试题

    1.列举ASP.NET页面之间传值的几种方式. 答:使用QueryString,如.../id=1;response.Redirect() 使用Session 使用Server.Transfer 使用 ...

  4. QQ顶部的消息,联系人切换

    高仿ios SegmentView 以前做过的一个项目美工设计的页面包含这个控件,和QQ消息页面顶部的效果一样,其实,这个控件是ios7的分段控制,android没有这个控件,不过实现起来也比较简单, ...

  5. PHP四种基本排序算法

    PHP的四种基本排序算法为:冒泡排序.插入排序.选择排序和快速排序. 下面是我整理出来的算法代码: 1. 冒泡排序: 思路:对数组进行多轮冒泡,每一轮对数组中的元素两两比较,调整位置,冒出一个最大的数 ...

  6. 算法改进 | java语言中判断素数

    参考文章:http://blog.csdn.net/kp_liu/article/details/37569507 http://blog.csdn.net/huang_miao_xin/articl ...

  7. 关于docker使用的几个小问题(二)

    很久没写博客了,集中写几个比较有意思的小问题. 一.CentOS容器没有service命令 这是因为我们从docker官方镜像仓库中pull的最新CentOS镜像都是centos7.4 Redhat- ...

  8. 02-从零玩转JavaWeb-类与对象

    配套视频:对象与类 一.什么是对象 包含特性和行为的一个实体   下图当中,"颜色"和"体重"属于"特性或叫状态" "咬人&quo ...

  9. Abp异常-找不到方法:“System.String Abp.Runtime.Security.SimpleStringCipher.Decrypt(System.String, System.String, Byte[])”

    解决方法:升级Abp.Zero版本到2.0.2

  10. 【ThinkPHP框架学习 】(1) --- thinkphp 3.2.3 验证码验证使用教程分享

    框架版本:ThinkPHP框架     thinkphp 3.2.3 生成验证码 下面是最简单的方式生成验证码: $Verify = new \Think\Verify(); $Verify-> ...