disruptor笔记之八:知识点补充(终篇)

伪共享

  • 下图是多核处理器的CPU缓存,可见每个核都有自己的L1和L2缓存,而L3缓存是共享的:

在这里插入图片描述

  • 假设disruptor的Sequence是long型,那么一个生产者和一个消费者的disruptor应该有两个long型Sequence,在L1中缓存这两个数字时,因为每个缓存行大小是64字节,所以两个Sequence很有可能在一个缓存行中

  • 此时如果程序修改了生产者Sequence的值,就会让L1上对应的缓存行失效,再从Main memory中读取最新的值,此时因为消费者Sequence也在同一个缓存行中,因此也被失效了,这就导致一个没有变化的值也被清理掉,还要再去Main memory中取一次,这是影响性能的行为

  • 看到这里,聪明的您一定想到解决问题的思路:不要让两个Sequence在同一个缓存行中

  • 具体的手段呢?您有没有联想到日常生活中的占座位,在身边座位放个背包,其他人就不能使用了(这是不文明行为,仅举例用)

  • 实际上disruptor用的也是占座的套路,咱们来看看Sequence的源码就一目了然了,如下图所示,Sequence的值是Value对象的成员变量value:

// 父类,

class LhsPadding

{

protected long p1, p2, p3, p4, p5, p6, p7;

}

class Value extends LhsPadding

{

protected volatile long value;

}

class RhsPadding extends Value

{

protected long p9, p10, p11, p12, p13, p14, p15;

}

public class Sequence extends RhsPadding

{

  • 类图如下,可见Value的父子类中都是占位的long型:

在这里插入图片描述

  • 因此,Sequence对象有16个成员变量,在L1 cache中是下图的排列方式:

在这里插入图片描述

  • 想像一下,L1 cache的缓存行,每64字节为一个,也就是说上面那一串,每八个就占据一个缓存行(每个long型8字节),于是就有以下三种排列的可能:
  1. V出现在一个缓存行的首位;

  2. V出现在一个缓存行的末尾;

  3. V出现在一个缓存行的首位和末尾之间的其他六个位置之一;

  • 也就是下图三种可能(U是L1 cache中的其他内容),可见不论哪种可能,V都能用P把自己所在缓存行全部占座,这样就不会出现两个Sequence出现在同一个缓存行的情况了:

在这里插入图片描述

Translators

  • Translators是个小的编程技巧,disruptor帮使用者做了些封装,让发布事件的代码更简洁;

  • 打开disruptor-tutorials项目的consume-mode这个module,回顾一下,业务发布事件要调用的方法,在OrderEventProducer.java中:

public void onData(String content) {

// ringBuffer是个队列,其next方法返回的是下最后一条记录之后的位置,这是个可用位置

long sequence = ringBuffer.next();

try {

// sequence位置取出的事件是空事件

OrderEvent orderEvent = ringBuffer.get(sequence);

// 空事件添加业务信息

orderEvent.setValue(content);

} finally {

// 发布

ringBuffer.publish(sequence);

}

}

  • 上面的代码中,其实开发者最关注的是orderEvent.setValue(content)这部分,其他几行是我从官方demo抄的…

  • 显然disruptor也发现了这个小问题,于是从3.0版本开始提供了EventTranslatorOneArg接口,开发者将业务逻辑放入放在此接口的实现类中,至于前面代码中的ringBuffer.next()、ringBuffer.get(sequence)这些,以及try-finally代码块这些东西统统都省去了,咱们可以将OrderEventProducer.java改造成一个新的类,代码如下,可见新增内部类EventTranslatorOneArg,里面是将数据转为事件的业务逻辑,对外提供调用的onData方法中,只需一行代码即可,和业务无关的代码全部省掉了:

package com.bolingcavalry.service;

import com.lmax.disruptor.EventTranslatorOneArg;

import com.lmax.disruptor.RingBuffer;

public class OrderEventProducerWithTranslator {

// 存储数据的环形队列

private final RingBuffer ringBuffer;

public OrderEventProducerWithTranslator(RingBuffer ringBuffer) {

this.ringBuffer = ringBuffer;

}

/**

  • 内部类

*/

private static final EventTranslatorOneArg<OrderEvent, String> TRANSLATOR = new EventTranslatorOneArg<OrderEvent, String>() {

@Override

public void translateTo(OrderEvent event, long sequence, String arg0) {

event.setValue(arg0);

}

};

public void onData(String content) {

ringBuffer.publishEvent(TRANSLATOR, content);

}

}

  • 在consume-mode中,上述代码有对应的服务类TranslatorPublishServiceImpl.java,并且有对应的单元测试代码(ConsumeModeServiceTest.testTranslatorPublishService),这里就不占篇幅了,您若有兴趣可以自行查阅;

  • 看看ringBuffer.publishEvent的内部实现,是如何帮咱们省去之前那几行的,首先是调用了sequencer.next:

@Override

public void publishEvent(EventTranslatorOneArg<E, A> translator, A arg0)

{

final long sequence = sequencer.next();

translateAndPublish(translator, sequence, arg0);

}

  • 再打开translateAndPublish看看,ringBuffer.get、try-finally代码块、sequencer.publish都在,这下放心了,以前咱们做的事情,现在disruptor帮我们做了,咱们可以专心业务逻辑了:

private void translateAndPublish(EventTranslatorOneArg<E, A> translator, long sequence, A arg0)

{

try

{

translator.translateTo(get(sequence), sequence, arg0);

}

finally

{

sequencer.publish(sequence);

}

}

Lambda风格

  • disruptor的重要API也支持Lambda表达式作为入参,这里将几处常用的API整理如下:
  1. Disruptor类实例化(LambdaServiceImpl.java):

// lambda类型的实例化

disruptor = new Disruptor(OrderEvent::new, BUFFER_SIZE, DaemonThreadFactory.INSTANCE);

  1. 设置事件消费者的时候,可以用Lambda取代之前的对象(LambdaServiceImpl.java):

// lambda表达式指定具体消费逻辑

disruptor.handleEventsWith((event, sequence, endOfBatch) -> {

log.info(“lambda操作, sequence [{}], endOfBatch [{}], event : {}”, sequence, endOfBatch, event);

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Java)

最后

对于很多Java工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。

整理的这些资料希望对Java开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

再分享一波我的Java面试真题+视频学习详解+技能进阶书籍

美团二面惜败,我的凉经复盘(附学习笔记+面试整理+进阶书籍)

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

最后

对于很多Java工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。

整理的这些资料希望对Java开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

再分享一波我的Java面试真题+视频学习详解+技能进阶书籍

[外链图片转存中…(img-6Pi9TjBF-1713822821982)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 10
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
[JAVA工程师必会知识点之并发编程]1、现在几乎100%的公司面试都必须面试并发编程,尤其是互联网公司,对于并发编程的要求更高,并发编程能力已经成为职场敲门砖。2、现在已经是移动互联和大数据时代,对于应用程序的性能、处理能力、处理时效性要求更高了,传统的串行化编程无法充分利用现有的服务器性能。3、并发编程是几乎所有框架的底层基础,掌握好并发编程更有利于我们学习各种框架。想要让自己的程序执行、接口响应、批处理效率更高,必须使用并发编程。4、并发编程是中高级程序员的标配,是拿高薪的必备条件。 【主讲讲师】尹洪亮Kevin:现任职某互联网公司首席架构师,负责系统架构、项目群管理、产品研发工作。10余年软件行业经验,具有数百个线上项目实战经验。擅长JAVA技术栈、高并发高可用伸缩式微服务架构、DevOps。主导研发的蜂巢微服务架构已经成功支撑数百个微服务稳定运行【推荐你学习这门课的理由:知识体系完整+丰富学习资料】1、 本课程总计122课时,由五大体系组成,目的是让你一次性搞定并发编程。分别是并发编程基础、进阶、精通篇、Disruptor高并发框架、RateLimiter高并发访问限流吗,BAT员工也在学。2、课程附带附带3个项目源码,几百个课程示例,5个高清PDF课件。3、本课程0基础入门,从进程、线程、JVM开始讲起,每一个章节只专注于一个知识点,每个章节均有代码实例。 【课程分为基础篇、进阶篇、高级篇】一、基础篇基础篇从进程与线程、内存、CPU时间片轮训讲起,包含线程的3种创建方法、可视化观察线程、join、sleep、yield、interrupt,Synchronized、重入锁、对象锁、类锁、wait、notify、线程上下文切换、守护线程、阻塞式安全队列等内容。二、进阶篇进阶篇课程涵盖volatied关键字、Actomic类、可见性、原子性、ThreadLocal、Unsafe底层、同步类容器、并发类容器、5种并发队列、COW容器、InheritableThreadLocal源码解析等内容。三、精通篇精通篇课程涵盖JUC下的核心工具类,CountDownLath、CyclicBarrier、Phaser、Semaphore、Exchanger、ReentrantLock、ReentrantReadWriteLock、StampedLock、LockSupport、AQS底层、悲观锁、乐观锁、自旋锁、公平锁、非公平锁、排它锁、共享锁、重入锁、线程池、CachedThreadPool、FixedThreadPool、ScheduledThreadPool、SingleThreadExecutor、自定义线程池、ThreadFactory、线程池切面编程、线程池动态管理等内容,高并发设计模式,Future模式、Master Worker模式、CompletionService、ForkJoin等课程中还包含Disruptor高并发无锁框架讲解:Disruptor支持每秒600万订单处理的恐怖能力。深入到底层原理和开发模式,让你又懂又会用。高并发访问限流讲解:涵盖木桶算法、令牌桶算法、Google RateLimiter限流开发、Apache JMeter压力测试实战。 【学完后我将达到什么水平?】1、 吊打一切并发编程相关的笔试题、面试题。2、 重构自己并发编程的体系知识,不再谈并发色变。3、 精准掌握JAVA各种并发工具类、方法、关键字的原理和使用。4、 轻松上手写出更高效、更优雅的并发程序,在工作中能够提出更多的解决方案。  【面向人群】1、 总感觉并发编程很难、很复杂、不敢学习的人群。2、 准备跳槽、找工作、拿高薪的程序员。3、 希望提高自己的编程能力,开发出更高效、性能更强劲系统的人群。4、 想要快速、系统化、精准掌握并发编程的人群。【课程知识体系图】

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值