Java 7中的TransferQueue 以及 SynchronousQueue
Java7中加入了JSR 166y规范对集合类和并发类库的改进。其中的一项是增加了接口TransferQueue
和其实现类LinkedTransferQueue
。
TransferQueue继承了BlockingQueue(
BlockingQueue又
继承了Queue
)并扩展了一些新方法。BlockingQueue(和Queue)是Java 5中加入的接口,它是指这样的一个队列:当生产者向队列添加元素但队列已满时,生产者会被阻塞;当消费者从队列移除元素但队列为空时,消费者会被阻塞。
TransferQueue则更进一步,生产者会一直阻塞直到所添加到队列的元素被某一个消费者所消费(不仅仅是添加到队列里就完事)。新添加的transfer方法用来实现这种约束。顾名思义,阻塞就是发生在元素从一个线程transfer到另一个线程的过程中,它有效地实现了元素在线程之间的传递(以建立Java内存模型中的happens-before关系的方式)。
TransferQueue还包括了其他的一些方法:两个tryTransfer方法,一个是非阻塞的,另一个带有timeout参数设置超时时间的。还有两个辅助方法hasWaitingConsumer()和getWaitingConsumerCount()。
当我第一次看到TransferQueue时,首先想到了已有的实现类SynchronousQueue
。SynchronousQueue的队列长度为0,最初我认为这好像没多大用处,但后来我发现它是整个Java Collection Framework中最有用的队列实现类之一,特别是对于两个线程之间传递元素这种用例。
TransferQueue相比SynchronousQueue用处更广、更好用,因为你可以决定是使用BlockingQueue的方法(译者注:例如put方法)还是确保一次传递完成(译者注:即transfer方法)。在队列中已有元素的情况下,调用transfer方法,可以确保队列中被传递元素之前的所有元素都能被处理。Doug Lea说从功能角度来讲,LinkedTransferQueue实际上是ConcurrentLinkedQueue、SynchronousQueue(公平模式)和LinkedBlockingQueue的超集。而且LinkedTransferQueue更好用,因为它不仅仅综合了这几个类的功能,同时也提供了更高效的实现。
Joe Bowbeer提供了一篇William Scherer, Doug Lea, and Michael Scott的论文,在这篇论文中展示了LinkedTransferQueue的算法,性能测试的结果表明它优于Java 5的那些类(译者注:ConcurrentLinkedQueue、SynchronousQueue和LinkedBlockingQueue)。LinkedTransferQueue的性能分别是SynchronousQueue的3倍(非公平模式)和14倍(公平模式)。因为像ThreadPoolExecutor这样的类在任务传递时都是使用SynchronousQueue,所以使用LinkedTransferQueue来代替SynchronousQueue也会使得ThreadPoolExecutor得到相应的性能提升。考虑到executor在并发编程中的重要性,你就会理解添加这个实现类的重要性了。
Java 5中的SynchronousQueue使用两个队列(一个用于正在等待的生产者、另一个用于正在等待的消费者)和一个用来保护两个队列的锁。而LinkedTransferQueue使用CAS操作(译者注:参考wiki)实现一个非阻塞的方法,这是避免序列化处理任务的关键。这篇论文还罗列了很多的细节和数据,如果你感兴趣,非常值得一读。
SynchronousQueue
SynchronousQueue是这样 一种阻塞队列,其中每个 put 必须等待一个 take,反之亦然。同步队列没有任何内部容量,甚至连一个队列的容量都没有。
不能在同步队列上进行 peek,因为仅在试图要取得元素时,该元素才存在;
除非另一个线程试图移除某个元素,否则也不能(使用任何方法)添加元素;
也不能迭代队列,因为其中没有元素可用于迭代。队列的头是尝试添加到队列中的首个已排队线程元素; 如果没有已排队线程,则不添加元素并且头为 null。
对于其他 Collection 方法(例如 contains),SynchronousQueue 作为一个空集合。此队列不允许 null 元素。
同步队列类似于 CSP 和 Ada 中使用的 rendezvous 信道。
它非常适合于传递性设计,在这种设计中,在一个线程中运行的对象要将某些信息、
事件或任务传递给在另一个线程中运行的对象,它就必须与该对象同步。
对于正在等待的生产者和使用者线程而言,此类支持可选的公平排序策略。默认情况下不保证这种排序。
但是,使用公平设置为 true 所构造的队列可保证线程以 FIFO 的顺序进行访问。 公平通常会降低吞吐量,但是可以减小可变性并避免得不到服务。

注意1:它一种阻塞队列,其中每个 put 必须等待一个 take,反之亦然。
同步队列没有任何内部容量,甚至连一个队列的容量都没有。
注意2:它是线程安全的,是阻塞的。
注意3:不允许使用 null 元素。
注意4:公平排序策略是指调用put的线程之间,或take的线程之间。
公平排序策略可以查考ArrayBlockingQueue中的公平策略。
注意5:SynchronousQueue的以下方法很有趣:
* iterator() 永远返回空,因为里面没东西。
* peek() 永远返回null。
* put() 往queue放进去一个element以后就一直wait直到有其他thread进来把这个element取走。
* offer() 往queue里放一个element后立即返回,如果碰巧这个element被另一个thread取走了,offer方法返回true,认为offer成功;否则返回false。
* offer(2000, TimeUnit.SECONDS) 往queue里放一个element但是等待指定的时间后才返回,返回的逻辑和offer()方法一样。
* take() 取出并且remove掉queue里的element(认为是在queue里的。。。),取不到东西他会一直等。
* poll() 取出并且remove掉queue里的element(认为是在queue里的。。。),只有到碰巧另外一个线程正在往queue里offer数据或者put数据的时候,该方法才会取到东西。否则立即返回null。
* poll(2000, TimeUnit.SECONDS) 等待指定的时间然后取出并且remove掉queue里的element,其实就是再等其他的thread来往里塞。
* isEmpty()永远是true。
* remainingCapacity() 永远是0。
* remove()和removeAll() 永远是false。
转自:http://blog.csdn.net/hudashi/article/details/7076814
http://ifeve.com/java-transfer-queue/
http://www.cnblogs.com/wangzhongqiu/p/6441703.html
Java 7中的TransferQueue 以及 SynchronousQueue的更多相关文章
- 【Java并发编程】4、JDK7中TransferQueue的使用以及TransferQueue与SynchronousQueue的差别
转自:http://blog.csdn.net/aitangyong/article/details/46472643 JDK7对JDK5中的J.U.C并发工具进行了增强,其中之一就是新增了Trans ...
- Java并发编程(您不知道的线程池操作), 最受欢迎的 8 位 Java 大师,Java并发包中的同步队列SynchronousQueue实现原理
Java_并发编程培训 java并发程序设计教程 JUC Exchanger 一.概述 Exchanger 可以在对中对元素进行配对和交换的线程的同步点.每个线程将条目上的某个方法呈现给 exchan ...
- JAVA语言中的修饰符
JAVA语言中的修饰符 -----------------------------------------------01--------------------------------------- ...
- Java开发中的23种设计模式详解
[放弃了原文访问者模式的Demo,自己写了一个新使用场景的Demo,加上了自己的理解] [源码地址:https://github.com/leon66666/DesignPattern] 一.设计模式 ...
- Java开发中的23种设计模式详解(转)
设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...
- Java语言中的面向对象特性总结
Java语言中的面向对象特性 (总结得不错) [课前思考] 1. 什么是对象?什么是类?什么是包?什么是接口?什么是内部类? 2. 面向对象编程的特性有哪三个?它们各自又有哪些特性? 3. 你知 ...
- 细分java环境中的JDK、JVM、JRE
细分java环境中的JDK.JVM.JRE 近来小看了下Android,扑面而来一堆概念JDK.JVM.JRE.SDK.NDK.ADT.缕了一下,其中JDK.JVM.JRE是java环境的东西,而SD ...
- Java学习过程中的总结的小知识点(长期更新)
Java学习过程中的总结的小知识点 (主要是自己不会的知识和容易搞错的东西) 计算某个程序运行的时间 long stime=System.currentTimeMillis(); copy3(file ...
- java project中 xml文件路径问题
xml文件默认是和src文件平级的,当不在project根目录下时,java代码中使用xml文件时需要写为这种形式:“/src/..../bean.xml”
随机推荐
- 11g等待事件之library cache: mutex X
11g等待事件之library cache: mutex X 作者: dbafree 日期: 2012 年 07 月 01 日发表评论 (0)查看评论 library cache: mutex X ...
- hdu1599(无向图的最小环模板)
题意:杭州有N个景区,景区之间有一些双向的路来连接,现在8600想找一条旅游路线,这个路线从A点出发并且最后回到A点,假设经过的路线为V1,V2,....VK,V1,那么必须满足K>2,就是说至 ...
- redis过期回调以及键空间通知
背景 最近需要涉及一个定时通知的业务,之前的办法是采用定时任务,每秒查询一次.后来了解到Redis的键空间通知机制,其中的过期通知,和业务非常贴合. 键空间通知 下面是Redis中文文档的介绍 键空间 ...
- 【Unity】AssetBundle的使用——打包/解包
最近参考了各位大神的资源,初步学习了Unity的资源管理模式,包括在编辑器管理(使用AssetDatabase)和在运行时管理(使用Resources和AssetBundle).在此简单总结运行时用A ...
- Java编程的逻辑 (44) - 剖析TreeSet
本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...
- layui栅格布局问题
在使用layer.open弹出到窗口中,使用布局一直不起作用. 开始到写法如下, 目的是一行分成左右两块,比例为8:4等分. <div class="layui-fluid" ...
- MVC个人网站开发笔记-150302
上传图片 参考这篇文章:http://www.cnblogs.com/kissdodog/archive/2012/12/15/2819025.html 调用ajaxFileUpload,控制器里面编 ...
- 25个最常用的iptables策略
1.清空存在的策略当你开始创建新的策略,你可能想清除所有的默认策略,和存在的策略,可以这么做:iptables -F 或者iptables --flush2,设置默认策略默认链策略是ACCEPT,改 ...
- 微信小程序——选中状态的切换
加入购物车的时候,往往会有产品相关属性的选择,比如:尺寸,规格等.像我做的项目中,就有一个门店的选择,如下图: 我们如何做到当前点击的这个高亮呢?今天就讲一下如何实现这个功能. 思路: 1.定义一个高 ...
- js文档碎片
//文档碎片:类似一个临时的文档,要所有要加的dom元素先放在这里,达到不要每次操作dom元素提高页面效率 var d1 = new Date(); //创建十个段落,常规的方式 ; i < ; ...