队列包含固定长度的队列和不固定长度的队列,队列的规则就是:先进先出。固定长度的队列往里放数据,如果放满了还要放,阻塞式队列就会等待,直到有数据取出,空出位置后才继续放;非阻塞式队列不能等待就只能报错了。

  查看Condition的JDK文档时,其中简单的模拟实现了阻塞队列的原理,Java中也已经为我们提供了阻塞队列ArrayBlockingQueue,其定义如下:

  public  interface  BlockingQueue<E>  extends  Queue<E>

  BlockingQueue 方法以四种形式出现,对于不能立即满足但可能在将来某一时刻可以满足的操作,这四种形式的处理方式不同:第一种是抛出一个异常,第二种是返回一个特殊值(null 或 false,具体取决于操作),第三种是在操作可以成功前,无限期地阻塞当前线程,第四种是在放弃前只在给定的最大时间限制内阻塞。下表中总结了这些方法:

  抛出异常 特殊值 阻 塞 超 时
插 入 add(e) offer(e) put(e) offer(e, time, unit)
移 除 remove() poll() take() poll(e, time, unit)
检 查 element() peek() 不可用 不可用

  

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

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

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

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

  java.util.concurrent.ArrayBlockingQueue<E>  E--在此 collection 中保持的元素类型

  extends AbstractQueue<E> implements BlockingQueue<E>, Serializable

  一个由数组支持的有界阻塞队列。此队列按 FIFO(先进先出)原则对元素进行排序。队列的头部 是在队列中存在时间最长的元素。队列的尾部是在队列中存在时间最短的元素。新元素插入到队列的尾部,队列获取操作则是从队列头部开始获得元素。

  这是一个典型的"有界缓存区",固定大小的数组在其中保持生产者插入的元素和使用者提取的元素。一旦创建了这样的缓存区,就不能再增加其容量。试图向已满队列中放入元素会导致操作受阻塞;试图从空队列中提取元素将导致类似阻塞。

  此类支持对等待的生产者线程和消费者线程进行排序的可选公平策略。默认情况下,不保证是这种排序。然而,通过将公平性 (fairness) 设置为 true 而构造的队列允许按照FIFO 顺序访问线程。公平性通常会降低吞吐量,但也减少了可变性和避免了“不平衡性”。

对应构造方法摘要:

  ArrayBlockingQueue(int capacity)          创建一个带有给定的(固定)容量和默认访问策略的 ArrayBlockingQueue

    ArrayBlockingQueue(int capacity, boolean fair)  创建一个具有给定的(固定)容量和指定访问策略的 ArrayBlockingQueue

    ArrayBlockingQueue(int capacity, boolean fair, Collection<? extends E> c)

   创建一个具有给定的(固定)容量和指定访问策略的 ArrayBlockingQueue,它最初包含给定 collection 的元素,并以 collection 迭代器的遍历顺序添加元素

方法摘要:

  boolean  add(E e) 将指定的元素插入此队列的尾部(如果立即可行且不会超过该队列的容量),在成功时返回 true,如果此队列已满,则抛异常

  void  clear()    自动移除此队列中的所有元素

  boolean  contains(Object o)  如果此队列包含指定的元素,则返回 true

  int  drainTo(Collection<E> c)   移除此队列中所有可用的元素,并将它们添加到给定 collection 中

  int  drainTo(Collection<E> c, int maxElements)  最多从此队列中移除给定数量的可用元素,并将这些元素添加到给定 collection 中

  ......

  这里我就不冗余多写这些方法的介绍了,有用到或者感兴趣的直接查文档即可。

  阻塞队列与Semaphore有些相似,但也不同,阻塞队列是一方存放数据,另一方释放数据,Semaphore通常则是由同一方设置和释放信号量。ArrayBlockingQueue只有put方法和take方法才具有阻塞功能,其他的不是得到一个指定的特殊值就是抛异常。
应用案例:
     用3个空间的队列来演示阻塞队列的功能和效果。

 import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue; public class BlockingQueueTest {
public static void main(String[] args) {
//创建具有3个大小容量的阻塞队列
final BlockingQueue queue = new ArrayBlockingQueue(3);
for (int i = 0; i < 2; i++) { //分别启动3个写入和取出阻塞队列数据线程
new Thread() {
public void run() {
while (true) {
try {
Thread.sleep((long) (Math.random() * 1000));
System.out.println(String.format("%s 准备放入队列数据...", Thread.currentThread().getName()));
queue.put(1);
System.out.println(String.format("%s 已经放了数据,队列目前有 %d 个数据", Thread.currentThread().getName(), queue.size()));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
} new Thread() {
public void run() {
while (true) {
try {
Thread.sleep(1000);
System.out.println(String.format("%s 准备从队列取数据...", Thread.currentThread().getName()));
queue.take();
System.out.println(String.format("%s 已经取走了数据,队列目前有 %d 个数据", Thread.currentThread().getName(), queue.size()));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} }.start();
}
}

以上代码运行打印效果如下:

  

提示:欢迎继续参看我相关的下一篇博客:并发库应用之十二 & 常用集合问题汇总

并发库应用之十一 & 阻塞队列的应用的更多相关文章

  1. Java多线程与并发库高级应用-可阻塞的队列

    ArrayBlockQueue 可阻塞的队列 > 队列包含固定长度的队列和不固定长度的队列. > ArrayBlockQueue > 看BlockingQueue类的帮助文档,其中有 ...

  2. Java并发编程(十)阻塞队列

    使用非阻塞队列的时候有一个很大问题就是:它不会对当前线程产生阻塞,那么在面对类似消费者-生产者的模型时,就必须额外地实现同步策略以及线程间唤醒策略,这个实现起来就非常麻烦.但是有了阻塞队列就不一样了, ...

  3. Java并发(7):阻塞队列

    在前面我们接触的队列都是非阻塞队列,比如PriorityQueue.LinkedList(LinkedList是双向链表,它实现了Dequeue接口). 使用非阻塞队列的时候有一个很大问题就是:它不会 ...

  4. Java 并发系列之七:java 阻塞队列(7个)

    1. 基本概念 2. 实现原理 3. ArrayBlockingQueue 4. LinkedBlockingQueue 5. LinkedBlockingDeque 6. PriorityBlock ...

  5. Java并发(基础知识)—— 阻塞队列和生产者消费者模式

    1.阻塞队列                                                                                        Blocki ...

  6. Java并发机制(6)--阻塞队列

    Java并发编程:阻塞队列整理自:博客园-海子-http://www.cnblogs.com/dolphin0520/p/3933404.html 1.什么是阻塞队列 除了同步容器(Hashtable ...

  7. 并发库应用之十 & 多线程数据交换Exchanger应用

    申明:用大白话来说就是用于实现两个人之间的数据交换,每个人在完成一定的事务后想与对方交换数据,第一个先拿出数据的人会一直等待第二个人,直到第二个人拿着数据到来时,才能彼此交换数据. java.util ...

  8. java并发之阻塞队列LinkedBlockingQueue与ArrayBlockingQueue

    Java中阻塞队列接口BlockingQueue继承自Queue接口,并提供put.take阻塞方法.两个主要的阻塞类实现是ArrayBlockingQueue和LinkedBlockingQueue ...

  9. 转: 【Java并发编程】之二十一:并发新特性—阻塞队列和阻塞栈(含代码)

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17511147 阻塞队列 阻塞队列是Java5并发新特性中的内容,阻塞队列的接口是Java. ...

随机推荐

  1. 怎样使用projectproperty sheet(.vsprops)来管理工程

    怎样使用projectproperty sheet(.vsprops)来管理工程 IDE:VS2005 前言 Project Property Sheet的意思是项目属性表,在大型项目中基本上都会使用 ...

  2. 【Qt编程】基于Qt的词典开发系列<二>--本地词典的设计

    我设计的词典不仅可以实现在线查单词,而且一个重大特色就是具有丰富的本地词典库:我默认加入了八个类型的词典,如下所示: 由于是本人是通信专业,因此加入了华为通信词典.电子工程词典,又由于我喜爱编程,也加 ...

  3. ffdshow 源代码分析 5: 位图覆盖滤镜(总结)

    ===================================================== ffdshow源代码分析系列文章列表: ffdshow 源代码分析 1: 整体结构 ffds ...

  4. RecyclerView添加Header和Footer

    使用过RecyclerView的同学就知道它并没有添加header和footer的方法,而ListView和GirdView都有,但是开发过程中难免有需求需要添加一个自定义的header或者foote ...

  5. OpenCV——PS 图层混合算法 (四)

    具体的算法原理可以参考 PS图层混合算法之四(亮光, 点光, 线性光, 实色混合) // PS_Algorithm.h #ifndef PS_ALGORITHM_H_INCLUDED #define ...

  6. 高仿qq健康

    概述 学习别人的代码,在此基础上 优化代码结构 增加动画 要点记录 通过mRatio参数,让宽高始终是一个比例 贝塞尔曲线手动画矩形圆角 画虚线 根据基准点绘制文字 属性动画的使用 画笔宽度的自适应 ...

  7. 创建Sencha touch第一个应用

    最近学习Sencha touch ,是一个菜鸟级别.废话不多说,让我们来创建Sencha touch的第一应用. 首先,我们下载Sencha touch2.0 sdk 和SDK工具.  SDK工具直接 ...

  8. 操作json数据

    删除: delete json[key] 把json字符串转成jsonObject : eval(+'('+json+')'+) 把jsonObject 转换成json字符串 :json.toJSON ...

  9. android DialogFragment 实现Dialog展示扫二维码图片展示

    近期开发项目,做个按钮点击弹出展示微信二维码关注微信公众号的展示框,于是想到DialogFragment,期间对Dialog的title的底框字体颜色做出相关设置,记录如下: 下面是 DialogFr ...

  10. PuTTY的下载安装和基本使用方法教程

    PuTTY是一款开源(Open Source Software)的连接软件,主要由Simon Tatham维护,使用MIT许可证授权.包含的组件有:PuTTY, PuTTYgen,PSFTP, PuT ...