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

  查看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. eclipse搭建ssh后台

    SSH框架是最常用的框架之一,在搭建SSH框架的时候总有人遇到这样,那样的问题.下面我介绍一下SSH框架搭建的全过程.  第一步:准备工作.    下载好eclipse,Struts2,Spring, ...

  2. Linux 打开句柄限制的调整

    Linux 打开句柄限制的调整 参考文章: Linux---进程句柄限制总结(http://blog.csdn.net/jhcsdb/article/details/32338953) !! 本文内容 ...

  3. C++链表模板类

    思想和上篇文章差不多,只是换了层包装. 直接上代码: // linklist.h #include <iostream> #include <cstdio> using nam ...

  4. Android 常用的ORM框架详解

    1. OrmLite OrmLite 不是 Android 平台专用的ORM框架,它是Java ORM.支持JDBC连接,Spring以及Android平台.语法中广泛使用了注解(Annotation ...

  5. Linux常用命令(第二版) --文件管理命令

    文件管理命令 并不建议:照着像命令大全这类的书来学! 常用命令大约有200个. 文件命名规则: a)除了'/'之外所有字符都合法! b)这些字符最好不用 1.空格符,制表符,退格符 2.连接符 3.特 ...

  6. OpenCV——PS 图层混合算法 (三)

    具体的算法原理可以参考 PS图层混合算法之三(滤色, 叠加, 柔光, 强光) // PS_Algorithm.h #ifndef PS_ALGORITHM_H_INCLUDED #define PS_ ...

  7. 图片验证码demo示例

    1.首先我们需要一个生成图片验证码图片的一个工具类(下方会有代码示例) 代码如下: package com.util; import java.awt.BasicStroke; import java ...

  8. combination sum、permutation、subset(组合和、全排列、子集)

    combination sum I.permutation I.subsets  I 是组合和.全排列.子集的第一种情况,给定数组中没有重复的元素. combination sum II.permut ...

  9. 学习MQ(一) 感知

    声明:我的文字里出现的MQ,如没有特殊指明,就是指的IBM的websphere MQ 以前对MQ一无所知! MQ是IBM websphere的系列产品之一,是很好的一个中间件产品.其实我对这列产品并不 ...

  10. 一个基础的for循环面试题

    下面的这段程序主要考察的就是for循环的基础,输出什么?????? [html] view plaincopyprint? public class test { /** * @param args ...