转自:http://blog.csdn.net/aitangyong/article/details/46472643

JDK7对JDK5中的J.U.C并发工具进行了增强,其中之一就是新增了TransferQueue。Java并发相关的JSR规范,可以查看Doug Lea维护的blog。现在简单介绍下这个类的使用方式。

  1. public interface TransferQueue<E> extends BlockingQueue<E>
  2. {
  3. /**
  4. * Transfers the element to a waiting consumer immediately, if possible.
  5. *
  6. * <p>More precisely, transfers the specified element immediately
  7. * if there exists a consumer already waiting to receive it (in
  8. * {@link #take} or timed {@link #poll(long,TimeUnit) poll}),
  9. * otherwise returning {@code false} without enqueuing the element.
  10. *
  11. * @param e the element to transfer
  12. * @return {@code true} if the element was transferred, else
  13. *         {@code false}
  14. * @throws ClassCastException if the class of the specified element
  15. *         prevents it from being added to this queue
  16. * @throws NullPointerException if the specified element is null
  17. * @throws IllegalArgumentException if some property of the specified
  18. *         element prevents it from being added to this queue
  19. */
  20. boolean tryTransfer(E e);
  21. /**
  22. * Transfers the element to a consumer, waiting if necessary to do so.
  23. *
  24. * <p>More precisely, transfers the specified element immediately
  25. * if there exists a consumer already waiting to receive it (in
  26. * {@link #take} or timed {@link #poll(long,TimeUnit) poll}),
  27. * else waits until the element is received by a consumer.
  28. *
  29. * @param e the element to transfer
  30. * @throws InterruptedException if interrupted while waiting,
  31. *         in which case the element is not left enqueued
  32. * @throws ClassCastException if the class of the specified element
  33. *         prevents it from being added to this queue
  34. * @throws NullPointerException if the specified element is null
  35. * @throws IllegalArgumentException if some property of the specified
  36. *         element prevents it from being added to this queue
  37. */
  38. void transfer(E e) throws InterruptedException;
  39. /**
  40. * Transfers the element to a consumer if it is possible to do so
  41. * before the timeout elapses.
  42. *
  43. * <p>More precisely, transfers the specified element immediately
  44. * if there exists a consumer already waiting to receive it (in
  45. * {@link #take} or timed {@link #poll(long,TimeUnit) poll}),
  46. * else waits until the element is received by a consumer,
  47. * returning {@code false} if the specified wait time elapses
  48. * before the element can be transferred.
  49. *
  50. * @param e the element to transfer
  51. * @param timeout how long to wait before giving up, in units of
  52. *        {@code unit}
  53. * @param unit a {@code TimeUnit} determining how to interpret the
  54. *        {@code timeout} parameter
  55. * @return {@code true} if successful, or {@code false} if
  56. *         the specified waiting time elapses before completion,
  57. *         in which case the element is not left enqueued
  58. * @throws InterruptedException if interrupted while waiting,
  59. *         in which case the element is not left enqueued
  60. * @throws ClassCastException if the class of the specified element
  61. *         prevents it from being added to this queue
  62. * @throws NullPointerException if the specified element is null
  63. * @throws IllegalArgumentException if some property of the specified
  64. *         element prevents it from being added to this queue
  65. */
  66. boolean tryTransfer(E e, long timeout, TimeUnit unit)
  67. throws InterruptedException;
  68. /**
  69. * Returns {@code true} if there is at least one consumer waiting
  70. * to receive an element via {@link #take} or
  71. * timed {@link #poll(long,TimeUnit) poll}.
  72. * The return value represents a momentary state of affairs.
  73. *
  74. * @return {@code true} if there is at least one waiting consumer
  75. */
  76. boolean hasWaitingConsumer();
  77. /**
  78. * Returns an estimate of the number of consumers waiting to
  79. * receive elements via {@link #take} or timed
  80. * {@link #poll(long,TimeUnit) poll}.  The return value is an
  81. * approximation of a momentary state of affairs, that may be
  82. * inaccurate if consumers have completed or given up waiting.
  83. * The value may be useful for monitoring and heuristics, but
  84. * not for synchronization control.  Implementations of this
  85. * method are likely to be noticeably slower than those for
  86. * {@link #hasWaitingConsumer}.
  87. *
  88. * @return the number of consumers waiting to receive elements
  89. */
  90. int getWaitingConsumerCount();
  91. }

可以看到TransferQueue同时也是一个阻塞队列,它具备阻塞队列的所有特性,主要介绍下上面5个新增API的作用。

1.transfer(E e)若当前存在一个正在等待获取的消费者线程,即立刻将e移交之;否则将元素e插入到队列尾部,并且当前线程进入阻塞状态,直到有消费者线程取走该元素。

  1. public class TransferQueueDemo {
  2. private static TransferQueue<String> queue = new LinkedTransferQueue<String>();
  3. public static void main(String[] args) throws Exception {
  4. new Productor(1).start();
  5. Thread.sleep(100);
  6. System.out.println("over.size=" + queue.size());
  7. }
  8. static class Productor extends Thread {
  9. private int id;
  10. public Productor(int id) {
  11. this.id = id;
  12. }
  13. @Override
  14. public void run() {
  15. try {
  16. String result = "id=" + this.id;
  17. System.out.println("begin to produce." + result);
  18. queue.transfer(result);
  19. System.out.println("success to produce." + result);
  20. } catch (InterruptedException e) {
  21. e.printStackTrace();
  22. }
  23. }
  24. }
  25. }

可以看到生产者线程会阻塞,因为调用transfer()的时候并没有消费者在等待获取数据。队列长度变成了1,说明元素e没有移交成功的时候,会被插入到阻塞队列的尾部。

2.tryTransfer(E e)若当前存在一个正在等待获取的消费者线程,则该方法会即刻转移e,并返回true;若不存在则返回false,但是并不会将e插入到队列中。这个方法不会阻塞当前线程,要么快速返回true,要么快速返回false。

3.hasWaitingConsumer()和getWaitingConsumerCount()用来判断当前正在等待消费的消费者线程个数。

4.tryTransfer(E e, long timeout, TimeUnit unit) 若当前存在一个正在等待获取的消费者线程,会立即传输给它; 否则将元素e插入到队列尾部,并且等待被消费者线程获取消费掉。若在指定的时间内元素e无法被消费者线程获取,则返回false,同时该元素从队列中移除。

  1. public class TransferQueueDemo {
  2. private static TransferQueue<String> queue = new LinkedTransferQueue<String>();
  3. public static void main(String[] args) throws Exception {
  4. new Productor(1).start();
  5. Thread.sleep(100);
  6. System.out.println("over.size=" + queue.size());//1
  7. Thread.sleep(1500);
  8. System.out.println("over.size=" + queue.size());//0
  9. }
  10. static class Productor extends Thread {
  11. private int id;
  12. public Productor(int id) {
  13. this.id = id;
  14. }
  15. @Override
  16. public void run() {
  17. try {
  18. String result = "id=" + this.id;
  19. System.out.println("begin to produce." + result);
  20. queue.tryTransfer(result, 1, TimeUnit.SECONDS);
  21. System.out.println("success to produce." + result);
  22. } catch (Exception e) {
  23. e.printStackTrace();
  24. }
  25. }
  26. }
  27. }

第一次还没到指定的时间,元素被插入到队列中了,所有队列长度是1;第二次指定的时间片耗尽,元素从队列中移除了,所以队列长度是0。

这篇文章中讲了SynchronousQueue的使用方式,可以看到TransferQueue也具有SynchronousQueue的所有功能,但是TransferQueue的功能更强大。这篇文章中提到了这2个API的区别:

  1. TransferQueue is more generic and useful than SynchronousQueue however as it allows you to flexibly decide whether to use normal BlockingQueue
  2. semantics or a guaranteed hand-off. In the case where items are already in the queue, calling transfer will guarantee that all existing queue
  3. items will be processed before the transferred item.
  4. SynchronousQueue implementation uses dual queues (for waiting producers and waiting consumers) and protects both queues with a single lock. The
  5. LinkedTransferQueue implementation uses CAS operations to form a nonblocking implementation and that is at the heart of avoiding serialization
  6. bottlenecks.

【Java并发编程】4、JDK7中TransferQueue的使用以及TransferQueue与SynchronousQueue的差别的更多相关文章

  1. Java并发编程(3) JUC中的锁

    一 前言 前面已经说到JUC中的锁主要是基于AQS实现,而AQS(AQS的内部结构 .AQS的设计与实现)在前面已经简单介绍过了.今天记录下JUC包下的锁是怎么基于AQS上实现的 二 同步锁 同步锁不 ...

  2. Java并发编程:JDK中的阻塞队列

    上次我们讲了一些常用的4个阻塞队列,但是在JDK中还提供了其他的一些阻塞队列.这篇文章将全面介绍一下JDK中的所有阻塞队列,并比较他们的区别. JDK7提供了7个阻塞队列.分别是 ArrayBlock ...

  3. 整理一下《java并发编程实战》中的知识点

    分工.同步.互斥的历史由来 分工:单道.多道.分时 同步:线程通信(组织编排任务) 互斥:因(多线程访问共享资源)果(串行化共享资源的访问) 1切都是为了提高性能 2.可见性.原子性.有序性 可见性: ...

  4. Java并发编程面试题 Top 50 整理版

    本文在 Java线程面试题 Top 50的基础上,对部分答案进行进行了整理和补充,问题答案主要来自<Java编程思想(第四版)>,<Java并发编程实战>和一些优秀的博客,当然 ...

  5. Java并发编程73道面试题及答案 —— 面试稳了

    今天主要整理一下 Java 并发编程在面试中的常见问题,希望对需要的读者有用. 1.在java中守护线程和本地线程区别? java中的线程分为两种:守护线程(Daemon)和用户线程(User). 任 ...

  6. Java并发编程学习路线(转)

    以前特地学过并发编程,但是没怎么学进去,不太喜欢.最近发现,作为一个资深工程师,却没有完整深入系统的学习过,而反是现在的BAT大并发是必须的,感觉甚是惭愧. 故找了一片学习文章,如下,准备集中一段时间 ...

  7. Java并发编程学习路线

    一年前由于工作需要从微软技术栈入坑Java,并陆陆续续做了一个Java后台项目,目前在搞Scala+Java混合的后台开发,一直觉得并发编程是所有后台工程师的基本功,所以也学习了小一年Java的并发工 ...

  8. Java 并发编程-不懂原理多吃亏(送书福利)

    作者 | 加多 关注阿里巴巴云原生公众号,后台回复关键字"并发",即可参与送书抽奖!** 导读:并发编程与 Java 中其他知识点相比较而言学习门槛较高,从而导致很多人望而却步.但 ...

  9. java并发编程之美-阅读记录1

    1.1什么是线程? 在理解线程之前先要明白什么是进程,因为线程是进程中的一个实体.(线程是不会独立存在的) 进程:是代码在数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,线程则是进程中的 ...

  10. Java并发编程(您不知道的线程池操作), 最受欢迎的 8 位 Java 大师,Java并发包中的同步队列SynchronousQueue实现原理

    Java_并发编程培训 java并发程序设计教程 JUC Exchanger 一.概述 Exchanger 可以在对中对元素进行配对和交换的线程的同步点.每个线程将条目上的某个方法呈现给 exchan ...

随机推荐

  1. php根据修改时间删除指定目录下文件

    //$dir-文件地址,$files-存储返回数组,$type-查找文件类型组 public function read_dir($dir,&$files,$type) { if(!is_di ...

  2. MVC5控制器传值的三种方式(ViewData,ViewBag,TempData),刚刚学习MVC5的新手,希望各位大神多多指教

    mvc传值的三种方式:1.ViewData 在使用过程中需要类型转换 例子: ViewData["MyTitle"]="ViewData传值"; 引用: @Vi ...

  3. js 将一个数组插入到另一个数组的方法

    JavaScript将一个数组插入到另一个数组的方法.分享给大家供大家参考.具体分析如下: 1.通过Array.prototype.push.apply方法将一个数组插入到另外一个数组,下面的代码将数 ...

  4. 2018-2019-2 20175230 实验三《Java面向对象程序设计》实验报告

    目录 实验三 实验三 敏捷开发与XP实践 实验内容 实验要求 实验步骤 (一) 编码标准 (二)敏捷开发与XP (三)敏捷开发与XP 实验体会 实验三 实验三 敏捷开发与XP实践 实验内容 1.XP基 ...

  5. Linux Shell脚本编程提高(12)

    实际上Shell是一个命令解释器,它解释由用户输入的命令并且把它们送到内核,不仅如此,Shell有自己的编程语言用于对命令的编辑,它允许用户编写由shell命令组成的程序.Shel编程语言具有普通编程 ...

  6. [JavaScript] html5 video标签注意事项

    Chrome 66 禁止声音自动播放 声音无法自动播放这个在IOS/Android上面一直是个惯例,桌面版的Safari在2017年的11版本也宣布禁掉带有声音的多媒体自动播放功能,紧接着在2018年 ...

  7. D3.js (v3)+react框架 基础部分之认识选择集和如何绘制一个矢量图

    首先需要下载安装d3.js  :  yarn add d3 然后在组建中引入 :  import * as d3 from 'd3' 然后定义一个方法,在componentDidMount()这个钩子 ...

  8. centos 部署.netcore 开发环境

    .netcore 2.0的安装,安装前,先参考官方文档 https://www.microsoft.com/net/core#linuxcentos 先做微软的签名校验工作 # sudo rpm -- ...

  9. 多态、抽象类、接口_DAY09

    1:多态(掌握) (1)多态概念:一种事物的多种形态 (2)体现:父类的引用指向其子类的实例对象;接口的引用指向其实现类的实例对象 (3)特点: 成员方法:编译看左边,运行看右边 运行:子类重写的方法 ...

  10. Java8简明指南

    Java8简明指南 转载自并发编程网 – ifeve.com本文链接地址: Java8简明指南 欢迎来到Java8简明指南.本教程将一步一步指导你通过所有新语言特性.由短而简单的代码示例,带你了解如何 ...