参考资料:http://ifeve.com/java-synchronousqueue/
http://www.cnblogs.com/jackyuj/archive/2010/11/24/1886553.html
http://ifeve.com/java-blocking-queue/

BlockingQueue的几个API认识

方法 说明
boolean add(E e) 添加元素,返回true或者超出队列size上限后抛异常,若队列有大小限制时,官方更建议使用offer方法
boolean offer(E e) 添加元素,返回true或者false(超出队列size上限后)
void put(E e) throws InterruptedException 添加元素,无返回值,若空间不足则进入waiting状态直到有空间
boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException 添加元素,返回true或者false(等待时间已到但仍无可添加空间),若空间不足则等待一定时间直到成功或者放弃
E take() throws InterruptedException 获取队列头部元素,若没有可取元素则进入waiting状态
E poll(long timeout, TimeUnit unit) throws InterruptedException 获取队列头部元素,若没有可取元素则等待一定时间直到成功或者放弃
boolean remove(Object o) 删除元素

BlockingQueue派生出几个常用的类ArrayBlockingQueue/LinkedBlockingDeque/DelayQueue/PriorityBlockingQueue/SynchronousQueue,类图如下所示:

它们的一些特性:

  • ArrayBlockingQueue:以数组保存元素,初始化时必须指定队列的容量capacity,添加元素时若达到上限进入阻塞
  • LinkedBlockingDeque:以双向链表保存元素,初始化时可指定队列的容量,若不指定,capacity默认为Integer.MAX_VALUE,添加元素时若达到上限进入阻塞
  • DelayQueue:以PriorityQueue保存元表,只能获取已到过期时间的元素,否则得到null,无容量上限,理论上可无限添加元素
  • PriorityBlockingQueue:以数组保存元素,整个队列为一棵平衡二叉树,添加元素成功后对队列内元素重排序,无容量上限,理论上可无限添加元素
  • SynchronousQueue:无缓存队列,生产者线程对其的插入操作put必须等待消费者的移除操作take,反过来也一样

ArrayBlockingQueue的使用案例可参考Java多线程系列三——实现线程同步的方法,本文测试DelayQueue的使用,代码如下:

  1. import java.util.Arrays;
  2. import java.util.HashMap;
  3. import java.util.List;
  4. import java.util.Map;
  5. import java.util.concurrent.ArrayBlockingQueue;
  6. import java.util.concurrent.BlockingQueue;
  7. import java.util.concurrent.Callable;
  8. import java.util.concurrent.DelayQueue;
  9. import java.util.concurrent.Delayed;
  10. import java.util.concurrent.ExecutionException;
  11. import java.util.concurrent.ExecutorService;
  12. import java.util.concurrent.Executors;
  13. import java.util.concurrent.Future;
  14. import java.util.concurrent.TimeUnit;
  15.  
  16. /**
  17. * @Description 利用DelayQueue清除超时请求<br/>
  18. * 1. 主线程从工作队列取出任务处理完成后,把任务从超时队列移除<br/>
  19. * 2. 超时检查线程找到超时请求后,把任务从工作队列中移除
  20. */
  21. public class DelayQueueTest {
  22. public static void main(String[] args) throws InterruptedException, ExecutionException {
  23. int size = 36;
  24. DelayQueue<MyRequest> queue = new DelayQueue<>();// 用于记录是否超时的队列
  25. BlockingQueue<MyRequest> workQueue = new ArrayBlockingQueue<>(size);// 请求的队表
  26. Map<Integer, MyRequest> cache = new HashMap<>();// 请求与id的对照表
  27. for (int i = 0; i < size; i++) {// 初始化
  28. MyRequest impl = new MyRequest(i, System.nanoTime(), 120);
  29. queue.put(impl);
  30. workQueue.put(impl);
  31. cache.put(i, impl);
  32. }
  33. /**
  34. * 建立超时检查任务
  35. */
  36. Executors.newSingleThreadExecutor().submit(new Runnable() {
  37. @Override
  38. public void run() {
  39. while (queue.size() > 0) {
  40. try {
  41. MyRequest impl = queue.take();
  42. workQueue.remove(impl);// 若请求超时则把请求从队列中移除
  43. System.out.println(String.format("%s is timeout", impl));
  44. } catch (InterruptedException e) {
  45. e.printStackTrace();
  46. }
  47. }
  48. }
  49. });
  50. /**
  51. * 建2个线程消费请求
  52. */
  53. ExecutorService executorService = Executors.newFixedThreadPool(2);
  54. while (workQueue.size() > 0) {
  55. List<MyRequest> tasks = Arrays.asList(new MyRequest[] { workQueue.take(), workQueue.take() });
  56. List<Future<Integer>> futures = executorService.invokeAll(tasks);
  57. for (Future<Integer> future : futures) {
  58. queue.remove(cache.get(future.get()));// 若请求成功,则不需要再检查是否超时
  59. }
  60. }
  61. executorService.awaitTermination(Integer.MAX_VALUE, TimeUnit.DAYS);
  62. executorService.shutdown();
  63. }
  64. }
  65.  
  66. class MyRequest implements Delayed, Callable<Integer> {
  67. private int threadId;
  68. private long startTime;
  69. private long expiredTime;
  70.  
  71. public MyRequest(int threadId, long startTime, long timeout) {
  72. this.threadId = threadId;
  73. this.startTime = startTime;
  74. this.expiredTime = TimeUnit.SECONDS.toNanos(timeout) + System.nanoTime();
  75. }
  76.  
  77. @Override
  78. public Integer call() {
  79. try {
  80. Thread.sleep(TimeUnit.SECONDS.toMillis(10));
  81. } catch (InterruptedException e) {
  82. e.printStackTrace();
  83. }
  84. System.out.println(String.format("%s is ok", this));
  85. return threadId;
  86. }
  87.  
  88. @Override
  89. public int compareTo(Delayed arg0) {
  90. int rtn;
  91. if (arg0 == null || !(arg0 instanceof MyRequest)) {
  92. rtn = 1;
  93. } else {
  94. MyRequest impl = (MyRequest) arg0;
  95. rtn = startTime > impl.getStartTime() ? 1 : (startTime == impl.getStartTime() ? 0 : -1);
  96. }
  97. return rtn;
  98. }
  99.  
  100. @Override
  101. public long getDelay(TimeUnit unit) {
  102. return expiredTime - System.nanoTime();
  103. }
  104.  
  105. public long getStartTime() {
  106. return startTime;
  107. }
  108.  
  109. @Override
  110. public String toString() {
  111. return String.format("MyRequest [threadId=%s, startTime=%s, expiredTime=%s]", threadId, startTime, expiredTime);
  112. }
  113. }

Java多线程系列十——BlockingQueue的更多相关文章

  1. Java多线程系列--“JUC集合”07之 ArrayBlockingQueue

    概要 本章对Java.util.concurrent包中的ArrayBlockingQueue类进行详细的介绍.内容包括:ArrayBlockingQueue介绍ArrayBlockingQueue原 ...

  2. Java多线程系列--“JUC集合”08之 LinkedBlockingQueue

    概要 本章介绍JUC包中的LinkedBlockingQueue.内容包括:LinkedBlockingQueue介绍LinkedBlockingQueue原理和数据结构LinkedBlockingQ ...

  3. Java多线程系列--“JUC集合”09之 LinkedBlockingDeque

    概要 本章介绍JUC包中的LinkedBlockingDeque.内容包括:LinkedBlockingDeque介绍LinkedBlockingDeque原理和数据结构LinkedBlockingD ...

  4. Java多线程系列--“JUC线程池”01之 线程池架构

    概要 前面分别介绍了"Java多线程基础"."JUC原子类"和"JUC锁".本章介绍JUC的最后一部分的内容——线程池.内容包括:线程池架构 ...

  5. Java多线程系列--“JUC线程池”02之 线程池原理(一)

    概要 在上一章"Java多线程系列--“JUC线程池”01之 线程池架构"中,我们了解了线程池的架构.线程池的实现类是ThreadPoolExecutor类.本章,我们通过分析Th ...

  6. Java多线程系列--“JUC线程池”03之 线程池原理(二)

    概要 在前面一章"Java多线程系列--“JUC线程池”02之 线程池原理(一)"中介绍了线程池的数据结构,本章会通过分析线程池的源码,对线程池进行说明.内容包括:线程池示例参考代 ...

  7. java多线程系列(六)---线程池原理及其使用

    线程池 前言:如有不正确的地方,还望指正. 目录 认识cpu.核心与线程 java多线程系列(一)之java多线程技能 java多线程系列(二)之对象变量的并发访问 java多线程系列(三)之等待通知 ...

  8. Java多线程系列--“JUC锁”03之 公平锁(一)

    概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...

  9. Java多线程系列--“JUC锁”04之 公平锁(二)

    概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...

随机推荐

  1. linux下rename用法--批量重命名 转

    原文地址:https://www.cnblogs.com/hester/p/5615871.html Linux的rename 命令有两个版本,一个是C语言版本的,一个是Perl语言版本的,早期的Li ...

  2. 2018 百度之星 初赛 第六题 HDU6349

    三原色图  Accepts: 281  Submissions: 1261  Time Limit: 1500/1000 MS (Java/Others)  Memory Limit: 262144/ ...

  3. HDU 5573 Binary Tree【构造】

    几天前模拟区域赛的一道题,今天发现在草稿箱里直接补个博客. 感觉这还是一道很有意思的构造题. 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5573 ...

  4. 【微信小程序】开发实战 之 「开发框架MINA构成」

    小程序开发框架的目标是通过尽可能简单.高效的方式让开发者可以在微信中开发具有原生 APP 体验的服务. 微信团队为小程序提供的框架命名为MINA.MINA框架通过封装微信客户端提供的文件系统.网络通信 ...

  5. 【小记事】解除端口占用(Windows)

    开发中有时会因为端口占用而导致起项目时报错(如下图),这时候只要解除端口占用即可. 解除端口占用: 1.打开cmd(win+r),查看端口占用情况 netstat -ano | findstr 端口号 ...

  6. 51nod 马拉松30 C(构二分图+状压dp)

    题意 分析 考虑一个图能被若干简单环覆盖,那么一定是每个点恰好一个出度,恰好一个出度 于是类似最小路径覆盖的处理,我们可以把每个点拆成2个点i和i',如果有一条边(i,j),那么将i和j'连起来 那么 ...

  7. Linux查看日志三种命令(转载)

    第一种:查看实时变化的日志(比较吃内存) 最常用的: tail -f filename (默认最后10行,相当于增加参数 -n 10) Ctrl+c 是退出tail命令 其他情况: tail -n 2 ...

  8. DTrace scripts for Mac OS X

    http://www.cnblogs.com/Proteas/p/3727297.html http://dtrace.org/blogs/brendan/2011/10/10/top-10-dtra ...

  9. 无线网卡与本地连接不能同时使用&一机多网络的优先级设置

    无线网卡与本地连接不能同时使用&一机多网络的优先级设置 2012-05-30 20:39 初次记录 2012-08-09 10:32 修订 题目中的两个问题,其实都可以归结为一个问题,即网络优 ...

  10. Python pandas学习笔记

    参考文献:<Python金融大数据分析> #导入模块 import pandas as pd #生成dataframe df = pd.DataFrame([10,20,30,40], c ...