ArrayBlockingQueue, LinkedBlockingQueue, ConcurrentLinkedQueue, RingBuffer

1. ArrayBlockingQueue, LinkedBlockingQueue, ConcurrentLinkedQueue

ArrayBlockingQueue, LinkedBlockingQueue 继承自 BlockingQueue, 他们的特点就是 Blocking, Blocking 特有的方法就是 take() 和 put(), 这两个方法是阻塞方法, 每当队列容量满的时候, put() 方法就会进入wait, 直到队列空出来, 而每当队列为空时, take() 就会进入等待, 直到队列有元素可以 take()

ArrayBlockingQueue, LinkedBlockingQueue 区别在于 ArrayBlockingQueue 必须指定容量, 且可以指定 fair 变量, 如果 fair 为 true, 则会保持 take() 或者 put() 操作时线程的 block 顺序, 先 block 的线程先 take() 或 put(), fair 又内部变量 ReentrantLock 保证

ConcurrentLinkedQueue 通过 CAS 操作实现了无锁的 poll() 和 offer(), 他的容量是动态的, 由于无锁, 所以在 poll() 或者 offer() 的时候 head 与 tail 可能会改变, 所以它会持续的判断 head 与 tail 是否改变来保证操作正确性, 如果改变, 则会重新选择 head 与 tail. 而由于无锁的特性, 他的元素更新与 size 变量更新无法做到原子 (实际上它没有 size 变量), 所以他的 size() 是通过遍历 queue 来获得的, 在效率上是 O(n), 而且无法保证准确性, 因为遍历的时候有可能 queue size 发生了改变.

 

RingBuffer 是 Distruptor 中的一个用来替代 ArrayBlockingQueue 的队列, 它的思想在于长度可控, 且无锁, 只有在 blocking 的时候(没有数据的时候出队, 数据满的时候入队)会自旋. 实现原理是使用一个环形array, 生产者作为 tail, 消费者作为 head, 每生产一次 tail atomic++, 每消费一次 head atomic++, tail 不能超过 head 一圈(array size, 即队列满时 blocking), tail 不能超过自己tail一圈(即不能覆盖未被消费的值), head 不能超过 tail (即无可消费任务时 blocking), head 不能取到空值(取到空值时 blocking). blocking 使用一个 while 自旋来完成, 那么只要生产者消费者的速度相当时, 即可通过 atomicInteger(cas) 保证无锁, 而如果你需要在 blocking 的时候立即返回, 则 while 自旋都可以不需要. 相比于 ArrayBlockingQueue, 它可以绝大部分时间无锁, blocking 自旋, 相比于 concurrentLinkedQueue, 他又能做到长度限制. 代码如下:

public class RingBuffer<T> implements Serializable {/****/private static final long serialVersionUID = 6976960108708949038L;private volatile AtomicInteger head;private volatile AtomicInteger tail;private int length;final T EMPTY = null;private volatile T[] queue;public RingBuffer(Class<T> type, int length){this.head = new AtomicInteger(0);this.tail = new AtomicInteger(0);this.length = length == 0 ? 2 << 16 : length; // 默认2^16  this.queue = (T[]) Array.newInstance(type, this.length);}public void enQueue(T t){if(t == null) t= (T) new Object();// 阻塞 -- 避免多生成者循环生产同一个节点  while(this.getTail() - this.getHead() >= this.length);int ctail = this.tail.getAndIncrement();while(this.queue[this.getTail(ctail)] != EMPTY); // 自旋  this.queue[this.getTail(ctail)] = t;}public T deQueue(){T t = null;// 阻塞 -- 避免多消费者循环消费同一个节点  while(this.head.get() >= this.tail.get());int chead = this.head.getAndIncrement();while(this.queue[this.getHead(chead)] == EMPTY); // 自旋  t = this.queue[this.getHead(chead)];this.queue[this.getHead(chead)] = EMPTY;return t;}public int getHead(int index){return index & (this.length - 1);}public int getTail(int index) {return index & (this.length - 1);}public int getHead() {return head.get() & (this.length - 1);}public int getTail() {return tail.get() & (this.length - 1);}public T[] getQueue() {return queue;}public int getLength() {return length;}public void setLength(int length) {this.length = length;}}

 

 

转载于:https://www.cnblogs.com/zemliu/p/3823597.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/293449.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ASP.NET Core 中是否有 PostAsJsonAsync() 方法?

咨询区 LP13在 Asp.NET 中我一般都用 PostAsJsonAsync() 做数据提交&#xff0c;在 Asp.NET Core 时代我貌似没有找到&#xff0c;按照程序集的命名规范&#xff0c;我觉得应该也是由 Microsoft.AspNet.WebApi.Client 迁移到 Microsoft.AspNetCore.WebApi.Client 中。回答区 Je…

OSI七层模型的作用

第七层&#xff1a;应用层 数据 用户接口&#xff0c;提供用户程序“接口”。 第六层&#xff1a;表示层 数据 数据的表现形式&#xff0c;特定功能的实现&#xff0c;如数据加密。 第五层&#xff1a;会话层 数据 允许不同机器上的用户之间建立会话关系&#xff0c;如WINDOW…

MyBatis学习总结(17)——Mybatis分页插件PageHelper

2019独角兽企业重金招聘Python工程师标准>>> 如果你也在用Mybatis&#xff0c;建议尝试该分页插件&#xff0c;这一定是最方便使用的分页插件。 分页插件支持任何复杂的单表、多表分页&#xff0c;部分特殊情况请看重要提示。 想要使用分页插件&#xff1f;请看如何…

微信发力了,一键部署网站后端!

大家好&#xff0c;我是鱼皮。还记得么&#xff1f;之前我全程直播带大家从 0 到 1 做了一个包含前端、后端的 表情包网站项目 &#xff0c;支持搜索表情、自由裁切下载、给表情包配字等功能。爸爸表情包网站在线编辑下载但由于各方面的原因&#xff0c;我暂时将该网站战术下线…

数据可视化(9)--数据可视化6步法

在当前互联网&#xff0c;各种数据可视化图表层出不穷&#xff0c;本文尝试对数据可视化的方法进行归纳&#xff0c;整理成6步法。一般的数据图表都可以拆分成最基本的两类元素: 所描述的事物及这个事物的数值&#xff0c;我们暂且将其分别定义为指标和指标值。比如一个性别分布…

数据挖掘在呼叫中心的六大应用点

当前商业正在从“以产品为中心”到“以用户为中心”转变&#xff0c;很多企业将CRM作为企业成功的一个关键因素&#xff0c;呼叫中心作为影响用户最直接的渠道&#xff0c;起着至关重要的作用&#xff1b;利用数据挖掘技术&#xff0c;可以提高企业呼叫中心的效率的同时来增加客…

c++win32项目 如何显示后再删除一个绘图_iMATLAB 绘图扩展函数系列 | 让你绘图更自由(进阶专辑开篇)!...

本专辑参考了mathworks公司主页文件交换站的一些分享文件&#xff0c;遴选部分绘图扩展函数供初学者参考&#xff0c;仅用作学习资料传播&#xff0c;版权属于原作者&#xff0c;特此致谢。如有不妥&#xff0c;请联系删除。本专辑将持续更新&#xff0c;欢迎读者投稿自己绘图函…

HTML5:理解head

2019独角兽企业重金招聘Python工程师标准>>> HTML文档的head部分&#xff0c;通常包括指定页面标题&#xff0c;为搜索引擎提供关于页面本身的信息&#xff0c;加载样式表&#xff0c;以及加载JavaScript文件&#xff08;出于性能考虑&#xff0c;多数时候放在页面底…

Android之什么场景该使用单例模式总结

1、什么是单例模式 单例模式意味着只有一个对象,至于单例模式如何实现就不这里就不多说了,有很多种实现办法。 2、什么时候该使用单例模式?如果不使用单例模式会出现什么问题? 先举2个例子 例子1 当我们做得到最新的短信和最新的通话记录的时候,我们一般采…

Dapr项目应用探索

背景介绍前面文章对Dapr的基本信息进行了学习&#xff0c;接下来尝试将Dapr应用相关应用中。接下来一步步实现应用dapr功能。一、预期效果如上图应用Dapr点包含&#xff1a;a) 报表服务绑定统一数据源服务&#xff1a;接受更新通知  b) 业务系统调用报表操作:采用Dapr方式二、…

为什么当代人越来越不快乐?

全世界只有3.14 % 的人关注了爆炸吧知识小时候哭着哭着就笑了&#xff0c;长大后笑着笑着就哭了。生活不易&#xff0c;成年人叹气&#xff0c;房租水费&#xff0c;学习压力、工作不如意...各种无形的压力&#xff0c;压得人喘不过气。如果一绷得太紧&#xff0c;再坚韧的弦也…

解读C#正则表达式

为什么80%的码农都做不了架构师&#xff1f;>>> 多少年来&#xff0c;许多的编程语言和工具都包含对正则表达式的支持&#xff0c;.NET基础类库中包含有一个名字空间和一系列可以充分发挥规则表达式威力的类&#xff0c;而且它们也都与未来的Perl 5中的规则表达式兼…

《SAS编程与数据挖掘商业案例》学习笔记之十九

继续《SAS编程与数据挖掘商业案例》学习笔记&#xff0c;本文侧重数据处理实践&#xff0c;包括&#xff1a;HASH对象、自定义format、以及功能强大的正则表达式 一&#xff1a;HASH对象 Hash对象又称散列表&#xff0c;是根据关键码值而直接进行访问的数据结构&#xff0c;是根…

do { ....} while(0) 在宏里冗余的意义

do { ....} while(0) 在宏里冗余的意义 cocos2d-x提供了许多宏模板&#xff0c;如&#xff1a;CC_SAFE_RETAIN(p),CC_SAFE_DELETE(p) 等等 查看一下CC_SAFE_RETAIN的源码&#xff1a; #define CC_SAFE_RETAIN(p) do { if(p) { (p)->retain(); } } while(0) 为什么…

iphone换机数据迁移_iPhone迁移数据到Android(相册与短信)

2020年09月20日前言&#xff1a;卖掉iPhone7暂时回到Android手机&#xff0c;然后需要将iPhone内的资料迁移到新手机中。我尽量不使用第三方工具实现迁移工作。一般新手机都会有迁移助手&#xff0c;但是都不完美&#xff0c;毕竟是两个不同手机系统&#xff0c;很多东西还是需…

网关和路由的区别

网关&#xff1a;网关实质上是一个网络通向其他网络的IP地址。比如有网络A和网络B&#xff0c;网络A的IP地址范围为“192.168.1.1~192. 168.1.254”&#xff0c;子网掩码为255.255.255.0&#xff1b;网络B的IP地址范围为“192.168.2.1~192.168.2.254”&#xff0c;子网掩码为25…

Java里阻塞线程的三种实现方法

在日常开发中&#xff0c;我们有时会遇到遇到多线程处理任务的情况&#xff0c;JDK里提供了便利的 ThreadPoolExecutor以及其包装的工具类Executors。但是我们知道 ExecutorService.excute(Runnable r)是异步的&#xff0c;超过线程池处理能力的线程会被加入到执行队列里。有时…

使用 dotnet-outdated 维护项目 nuget 包版本

使用 dotnet-outdated 维护项目 nuget 包版本Intro我们项目中或多或少都会有一些 NuGet 包&#xff0c;使用到 NuGet 包时&#xff0c;如何保证我们的 NuGet 包不会太旧呢&#xff1f;我们可以借助 dotnet-outdated 来检查项目中的 NuGet 包是否有更新Sample首先我们需要执行 d…