BlockingQueue详解

本例介绍一个特殊的队列:BlockingQueue,如果BlockingQueue是空的,从BlockingQueue取东西的操作将会被阻断进入 等待状态,直到BlockingQueue进了东西才会被唤醒,同样,如果BlockingQueue是满的,任何试图往里存东西的操作也会被阻断进入等 待状态,直到BlockingQueue里有空间时才会被唤醒继续操作。
       本例再次实现前面介绍的篮子程序,不过这个篮子中最多能放得苹果数不是1,可以随意指定。当篮子满时,生产者进入等待状态,当篮子空时,消费者等待。

 BlockingQueue定义的常用方法如下:
                add(anObject):把anObject加到BlockingQueue里,如果BlockingQueue可以容纳,则返回true,否则抛出异常。
                offer(anObject):表示如果可能的话,将anObject加到BlockingQueue里,即如果BlockingQueue可以容纳,则返回true,否则返回false。
                put(anObject):把anObject加到BlockingQueue里,如果BlockingQueue没有空间,则调用此方法的线程被阻断直到BlockingQueue里有空间再继续。
                poll(time):取走BlockingQueue里排在首位的对象,若不能立即取出,则可以等time参数规定的时间,取不到时返回null。
                take():取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态直到BlockingQueue有新的对象被加入为止。

 BlockingQueue有四个具体的实现类,根据不同需求,选择不同的实现类:
                ArrayBlockingQueue:规定大小的BlockingQueue,其构造函数必须带一个int参数来指明其大小。其所含的对象是以FIFO(先入先出)顺序排序的。
                LinkedBlockingQueue:
大小不定的BlockingQueue,若其构造函数带一个规定大小的参数,生成的BlockingQueue有大小限制,若不带大小参数,所生成的
BlockingQueue的大小由Integer.MAX_VALUE来决定。其所含的对象是以FIFO顺序排序的。
                PriorityBlockingQueue:类似于LinkedBlockingQueue,但其所含对象的排序不是FIFO,而是依据对象的自然排序顺序或者是构造函数所带的Comparator决定的顺序。
                SynchronousQueue:特殊的BlockingQueue,对其的操作必须是放和取交替完成的。

 LinkedBlockingQueue
和ArrayBlockingQueue比较起来,它们背后所用的数据结构不一样,导致LinkedBlockingQueue的数据吞吐量要大于
ArrayBlockingQueue,但在线程数量很大时其性能的可预见性低于ArrayBlockingQueue。

[java] view plaincopy

    1. import java.util.concurrent.ArrayBlockingQueue;
    2. import java.util.concurrent.BlockingQueue;
    3. import java.util.concurrent.ExecutorService;
    4. import java.util.concurrent.Executors;
    5. /** *//**
    6. * BlockingQueue是一种特殊的Queue,若BlockingQueue是空的,
    7. * 从BlockingQueue取东西的操作将会被阻断进入等待状态直到BlocingkQueue进了新货才会被唤醒。
    8. * 同样,如果BlockingQueue是满的任何试图往里存东西的操作也会被阻断进入等待状态,
    9. * 直到BlockingQueue里有新的空间才会被唤醒继续操作。
    10. * BlockingQueue提供的方法主要有:
    11. * add(anObject): 把anObject加到BlockingQueue里,如果BlockingQueue可以容纳返回true,否则抛出IllegalStateException异常。
    12. * offer(anObject):把anObject加到BlockingQueue里,如果BlockingQueue可以容纳返回true,否则返回false。
    13. * put(anObject):把anObject加到BlockingQueue里,如果BlockingQueue没有空间,调用此方法的线程被阻断直到BlockingQueue里有新的空间再继续。
    14. * poll(time):取出BlockingQueue里排在首位的对象,若不能立即取出可等time参数规定的时间。取不到时返回null。
    15. * take():取出BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态直到BlockingQueue有新的对象被加入为止。
    16. *
    17. * 根据不同的需要BlockingQueue有4种具体实现:
    18. * (1)ArrayBlockingQueue:规定大小的BlockingQueue,其构造函数必须带一个int参数来指明其大小。其所含的对象是以FIFO(先入先出)顺序排序的。
    19. * (2)LinkedBlockingQueue:大小不定的BlockingQueue,若其构造函数带一个规定大小的参数,生成的BlockingQueue有大小限制,
    20. * 若不带大小参数,所生成的BlockingQueue的大小由Integer.MAX_VALUE来决定。其所含的对象是以FIFO(先入先出)顺序排序的。
    21. * LinkedBlockingQueue和ArrayBlockingQueue比较起来,它们背后所用的数据结构不一样,
    22. * 导致LinkedBlockingQueue的数据吞吐量要大于ArrayBlockingQueue,但在线程数量很大时其性能的可预见性低于ArrayBlockingQueue。
    23. * (3)PriorityBlockingQueue:类似于LinkedBlockingQueue,但其所含对象的排序不是FIFO,而是依据对象的自然排序顺序或者是构造函数所带的Comparator决定的顺序。
    24. * (4)SynchronousQueue:特殊的BlockingQueue,对其的操作必须是放和取交替完成的。
    25. *
    26. * 下面是用BlockingQueue来实现Producer和Consumer的例子
    27. */
    28. public class BlockingQueueTest {
    29. /** *//**
    30. * 定义装苹果的篮子
    31. */
    32. public static class Basket{
    33. // 篮子,能够容纳3个苹果
    34. BlockingQueue<String> basket = new ArrayBlockingQueue<String>(3);
    35. // 生产苹果,放入篮子
    36. public void produce() throws InterruptedException{
    37. // put方法放入一个苹果,若basket满了,等到basket有位置
    38. basket.put("An apple");
    39. }
    40. // 消费苹果,从篮子中取走
    41. public String consume() throws InterruptedException{
    42. // get方法取出一个苹果,若basket为空,等到basket有苹果为止
    43. return basket.take();
    44. }
    45. }
    46. // 测试方法
    47. public static void testBasket() {
    48. // 建立一个装苹果的篮子
    49. final Basket basket = new Basket();
    50. // 定义苹果生产者
    51. class Producer implements Runnable {
    52. public void run() {
    53. try {
    54. while (true) {
    55. // 生产苹果
    56. System.out.println("生产者准备生产苹果:"
    57. + System.currentTimeMillis());
    58. basket.produce();
    59. System.out.println("生产者生产苹果完毕:"
    60. + System.currentTimeMillis());
    61. // 休眠300ms
    62. Thread.sleep(300);
    63. }
    64. } catch (InterruptedException ex) {
    65. }
    66. }
    67. }
    68. // 定义苹果消费者
    69. class Consumer implements Runnable {
    70. public void run() {
    71. try {
    72. while (true) {
    73. // 消费苹果
    74. System.out.println("消费者准备消费苹果:"
    75. + System.currentTimeMillis());
    76. basket.consume();
    77. System.out.println("消费者消费苹果完毕:"
    78. + System.currentTimeMillis());
    79. // 休眠1000ms
    80. Thread.sleep(1000);
    81. }
    82. } catch (InterruptedException ex) {
    83. }
    84. }
    85. }
    86. ExecutorService service = Executors.newCachedThreadPool();
    87. Producer producer = new Producer();
    88. Consumer consumer = new Consumer();
    89. service.submit(producer);
    90. service.submit(consumer);
    91. // 程序运行5s后,所有任务停止
    92. try {
    93. Thread.sleep(5000);
    94. } catch (InterruptedException e) {
    95. }
    96. service.shutdownNow();
    97. }
    98. public static void main(String[] args) {
    99. BlockingQueueTest.testBasket();
    100. }
      1. 原文:http://hittyt.iteye.com/blog/1130990
时间: 2024-10-02 04:35:21

BlockingQueue详解的相关文章

java.util.concurrent BlockingQueue详解

什么是阻塞队列? 阻塞队列(BlockingQueue)是一个支持两个附加操作的队列.这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空.当队列满时,存储元素的线程会等待队列可用.阻塞队列常用于生产者和消费者的场景,生产者是往队列里添加元素的线程,消费者是从队列里拿元素的线程.阻塞队列就是生产者存放元素的容器,而消费者也只从容器里拿元素. 阻塞队列提供了四种处理方法: 方法\处理方式 抛出异常 返回特殊值 一直阻塞 超时退出 插入 add(e) offer(e) put(e) o

java并发容器(Map、List、BlockingQueue)详解

Java库本身就有多种线程安全的容器和同步工具,其中同步容器包括两部分:一个是Vector和Hashtable.另外还有JDK1.2中加入的同步包装类,这些类都是由Collections.synchronizedXXX工厂方法.同步容器都是线程安全的,但是对于复合操作,缺有些缺点: ① 迭代:在查觉到容器在迭代开始以后被修改,会抛出一个未检查异常ConcurrentModificationException,为了避免这个异常,需要在迭代期间,持有一个容器锁.但是锁的缺点也很明显,就是对性能的影响

ThreadPoolExecutor详解

ThreadPoolExecutor详解 ThreadPoolExecutor的完整构造方法的签名是:ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) . coreP

HBase RegionServer详解(未完)

HBase RegionServer详解 RegionServer组件介绍 RegionServer是HBase集群运行在每个工作节点上的服务.它是整个HBase系统的关键所在,一方面它维护了Region的状态,提供了对于Region的管理和服务:另一方面,它与Master交互,参与Master的分布式协调管理. MemStoreFlusher MemStoreFlusher主要功能是将MemStore刷新到文件中,当满足一下条件时会出发MemStore执行flush操作,最小的flush单元是

AsyncTask详解

http://blog.csdn.net/liuhe688/article/details/6532519 在Android中实现异步任务机制有两种方式,Handler和AsyncTask. Handler模式需要为每一个任务创建一个新的线程,任务完成后通过Handler实例向UI线程发送消息,完成界面的更新,这种方式对于整个过程的控制比较精细,但也是有缺点的,例如代码相对臃肿,在多个任务同时执行时,不易对线程进行精确的控制.关于Handler的相关知识,前面也有所介绍,不清楚的朋友们可以参照一

Java自带线程池和队列详解

Java线程池使用说明 一简介 线程的使用在java中占有极其重要的地位,在jdk1.4极其之前的jdk版本中,关于线程池的使用是极其简陋的.在jdk1.5之后这一情况有了很大的改观.Jdk1.5之后加入了java.util.concurrent包,这个包中主要介绍java中线程以及线程池的使用.为我们在开发中处理线程的问题提供了非常大的帮助. 二:线程池 线程池的作用: 线程池作用就是限制系统中执行线程的数量.     根据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果:少了浪

ExecutorCompletionService原理详解

在JDK并发包中有这么一个类ExecutorCompletionService,提交任务后,可以按任务返回结果的先后顺序来获取各任务执行后的结果. 该类实现了接口CompletionService: public interface CompletionService<V> { Future<V> submit(Callable<V> task); Future<V> submit(Runnable task, V result); Future<V&

AsyncTask机制详解

AsyncTask是Android提供的一个轻量级异步任务机制,使用AsyncTask可以方便的执行异步任务,并将结果更新到main thread.AsyncTask中是通过Handler机制来让work thread和main thread通信的.如果你对Handler还不了解的话,可以通过我的这篇博客来了解Android的Handler机制.Android 异步消息处理机制 在这篇文章中我们将了解AsyncTask的基本用法以及从源码的角度来分析AsyncTask机制,首先我们来了解下开发过

(转)详解Android中AsyncTask的使用

转载自:详解Android中AsyncTask的使用 在Android中实现异步任务机制有两种方式,Handler和AsyncTask. Handler模式需要为每一个任务创建一个新的线程,任务完成后通过Handler实例向UI线程发送消息,完成界面的更新,这种方式对于整个过程的控制比较精细,但也是有缺点的,例如代码相对臃肿,在多个任务同时执行时,不易对线程进行精确的控制.关于Handler的相关知识,前面也有所介绍,不清楚的朋友们可以参照一下. 为了简化操作,Android1.5提供了工具类a