高性能队列Disruptor使用教程

news2024/9/27 12:13:12

目录

  • 一、简介
  • 二、代码
    • 2.1 依赖
    • 2.2 角色介绍
    • 2.3 事件类
    • 2.4 生产者
    • 2.5 消费者
    • 2.6 启动Disruptor
    • 2.7 测试
  • 源码

一、简介

Disruptor是英国外汇交易公司LMAX开发的一个高性能队列,研发的初衷是解决内存队列的延迟问题(在性能测试中发现竟然与I/O操作处于同样的数量级)。由于其高性能,获得了很多大奖。
在美团技术团队它也有不少应用,有的项目架构借鉴了它的设计机制。
从数据结构上来看,Disruptor 是一个支持 生产者 -> 消费者 模式的 环形队列。能够在 无锁 的条件下进行并行消费,也可以根据消费者之间的依赖关系进行先后消费次序。

二、代码

2.1 依赖

  <dependency>
      <groupId>com.lmax</groupId>
      <artifactId>disruptor</artifactId>
      <version>3.4.2</version>
  </dependency>

2.2 角色介绍

Event :事件类:生产者和消费者之间进行交换的数据被称为事件(Event)。
Producer: 生产者,用于发布事件。
Consumer :消费者(实现EventHandler接口):用于处理事件。

Disruptor通过事件工厂EventFactory在RingBuffer中预创建事件Event的实例。
一个事件实例Event类似于一个数据槽。
生产者Producer发布Publish之前,先从Ringbuffer中获取一个事件Event实例。
然后生产者Producer向事件Event实例中填充数据,然后再发布到RingBuffer中。
最后由消费者Consumer获取事件Event实例并读取实例中的数据。

2.3 事件类

/**
 * @Author: LiuShihao
 * @Date: 2022/11/23 14:39
 * @Desc: 定义事件类:生产者和消费者之间进行交换的数据
 */
public class LogEvent {

    //事件类工厂:引用new方法
    public static final EventFactory<LogEvent> FACTORY = LogEvent::new;
    private String data;

    private Instant timestamp;

    public String getData() {
        return data;
    }

    public void setData(String data) {
        this.data = data;
    }

    public Instant getTimestamp() {
        return timestamp;
    }

    public void setTimestamp(Instant timestamp) {
        this.timestamp = timestamp;
    }

    @Override
    public String toString() {
        return "LogEvent{" +
                "data='" + data + '\'' +
                ", timestamp=" + timestamp +
                '}';
    }
}

2.4 生产者

/**
 * @Author: LiuShihao
 * @Date: 2022/11/23 14:39
 * @Desc: 生产者类:用于发布事件。
 */
public class MyProducer {

    //RingBuffer
    private final RingBuffer<LogEvent> ringBuffer;

    //有参构造
    public MyProducer(RingBuffer<LogEvent> ringBuffer) {
        this.ringBuffer = ringBuffer;
    }

    /**
     * 发布事件
     * @param eventObject
     */
    public void publish(LogEvent eventObject) {
        boolean isPublished = ringBuffer.tryPublishEvent((event, sequence) -> {
            event.setTimestamp(Instant.now());
            event.setData(eventObject.getData());
        });

        if (!isPublished) {
            System.err.println(Thread.currentThread().getName()+" - "+Thread.currentThread().getId() + " producer Failed to publish!");
        }
    }
}

2.5 消费者

/**
 * @Author: LiuShihao
 * @Date: 2022/11/23 14:39
 * @Desc: 消费者类:接收事件,实现EventHandler接口
 */
public class MyConsumer implements EventHandler<LogEvent> {
    @Override
    public void onEvent(LogEvent event, long sequence, boolean endOfBatch) throws Exception {
        System.out.println("consumer:"+event);
        Thread.sleep(3000);
    }
}

2.6 启动Disruptor

Disruptor的构造参数有5个:
在这里插入图片描述

  1. EventFactory:事件工厂类,用于生产事件。
  2. ringBufferSize:环形缓冲区的大小,必须是2的次幂。
  3. threadFactory:线程工厂,用于创建线程。
  4. ProducerType:事件生产者策略(单线程和多线程)。
  5. WaitStrategy:等待策略。

在这里插入图片描述

通过disruptor.handleEventsWith();方法设置消费者,方法内可以传入一个或者多个消费者。

 Disruptor<LogEvent> disruptor = new Disruptor<LogEvent>(
         LogEvent.FACTORY,
         2,
         Executors.defaultThreadFactory(),
         ProducerType.MULTI,
         new BlockingWaitStrategy()
 );
 disruptor.handleEventsWith(myConsumer);
 disruptor.start();

 MyProducer myProducer = new MyProducer(disruptor.getRingBuffer());

2.7 测试

/**
 * @Author: LiuShihao
 * @Date: 2022/11/23 14:38
 * @Desc:
 */
public class Main {
    public static void main(String[] args) {
        MyConsumer myConsumer = new MyConsumer();

        Disruptor<LogEvent> disruptor = new Disruptor<LogEvent>(
                LogEvent.FACTORY,
                2,
                Executors.defaultThreadFactory(),
                ProducerType.MULTI,
                new BlockingWaitStrategy()
        );
        disruptor.handleEventsWith(myConsumer);
        disruptor.start();

        MyProducer myProducer = new MyProducer(disruptor.getRingBuffer());

        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                LogEvent logEvent = LogEvent.FACTORY.newInstance();
                logEvent.setData(Thread.currentThread().getName());
                myProducer.publish(logEvent);
            }).start();
        }
    }
}

在这里插入图片描述

源码

https://github.com/Liu-Shihao/disruptor-demo.git

参考文章:
https://juejin.cn/post/6844904020973191181
https://juejin.cn/post/6844903976924610574
https://blog.51cto.com/u_15185289/3313032

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

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

相关文章

【C++】多态/虚表

目录 一、概念 二、虚表工作/运行原理 1.虚函数在一个类内存储的大小 2.对虚函数的访问&#xff08;一维数组&#xff09; 3.单继承 &#xff08;1&#xff09;虚函数继承情况 &#xff08;2&#xff09;单继承存储的大小 &#xff08;3&#xff09;基类子类调用情况 …

Actipro Windows Forms Controls 22.1.3 注册版

Actipro Windows Forms Controls 窗体控件 一组用于构建漂亮的 Windows 窗体桌面应用程序的 UI 控件 语法编辑器 语法高亮代码编辑器控件和解析套件。 为您自己的应用程序带来类似于 Visual Studio 的强大代码编辑体验&#xff0c;以及流行代码编辑器中的所有高级功能。大多数流…

二次封装 Spring Data JPA/MongoDB,打造更易用的数据访问层

本文正在参加「金石计划 . 瓜分6万现金大奖」 最近我在做一个新项目&#xff0c;由于我们项目组一直使用的是 MongoDB 数据库&#xff0c;所以新项目我就打算上 Spring Data MongoDB 尝试一下&#xff0c;虽然我早就用过了 Spring Data JPA&#xff0c;对 Spring Data 的相关 …

第四章《类与对象》第3节:方法的重载

方法的重载是Java语言中一项非常重要的机制。Java语言因为有了重载机制,使得程序员定义和调用方法都变得更加轻松。 4.3.1方法重载的概念及实现原理 4.2小节的Person类中定义了计算2个整数之和的add()方法,如果程序员为add()方法传递两个double型参数,则会因参数类型不兼容…

期末前端web大作业——HTML+CSS+JavaScript仿京东购物商城网页制作(7页)

常见网页设计作业题材有 个人、 美食、 公司、 学校、 旅游、 电商、 宠物、 电器、 茶叶、 家居、 酒店、 舞蹈、 动漫、 服装、 体育、 化妆品、 物流、 环保、 书籍、 婚纱、 游戏、 节日、 戒烟、 电影、 摄影、 文化、 家乡、 鲜花、 礼品、 汽车、 其他等网页设计题目, A…

聊一聊我对Restful的理解

概念 REST原则提倡按照HTTP的语义使用HTTP&#xff0c;如果一个系统符合REST原则&#xff0c;我们就说这个系统是Restful风格的。Restful是Web API设计中非常重要的一个概念&#xff0c;但是很多开发人员对于Restful的理解存在误区。 什么是Restful 在说什么是Restful 之前&…

数据结构之基数排序

基数排序 先把各个数以个位数不同分到不同的队列中 如果一个队列多个元素用链表连起来 第一趟分配 然后进行第一趟收集 应为我们想得到递减 所以我们从个位数高到低收集 然后第二趟分配 根据第一趟得到的结果 以十位数分配 这里注意&#xff01; 因为第一趟按个位分的&am…

ImmunoChemistry艾美捷高级钙素AM细胞活力试剂盒方案

ImmunoChemistry艾美捷ICT的Advanced Calcein AM Cell Viability Kit将Calcein AM与7-AAD相结合&#xff0c;可轻松同时标记单个样本中的活细胞、膜受损细胞和死细胞。钙黄绿素AM用于检测绿色荧光的活细胞&#xff0c;而7-AAD用于检测红色荧光的坏死或晚期凋亡细胞。可以使用流…

超详细curl新增支持openssl(https协议)支持

1、问题环境&#xff1a; os&#xff1a;Linux kali 5.5.0-kali2-amd64 #1 SMP Debian 5.5.17-1kali1 (2020-04-21) x86_64 GNU/Linux 2、涉及组件&#xff1a; curl当前版本&#xff1a;curl 7.85.0 openssl当前版本&#xff1a;OpenSSL 3.0.7 1 Nov 2022 (Library: OpenS…

学生个人网页设计作品 学生个人网页模板 简单个人主页成品 个人网页制作 HTML学生个人网站作业设计

&#x1f380; 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

遥感SCI期刊汇总

1. BOLETIM DE CIENCIAS GEODESICAS 《大地测量科学通报》http://ojs.c3sl.ufpr.br/ojs2/index.php/bcgSemiannual &#xff08;注&#xff1a;2008年开始被SCI收录&#xff09;ISSN: 1413-4853UNIV FEDERAL PARANA, CENTRO POLITECNICO, UFPR CENTRO POLITECNICO, CURSO POS…

如何使用云服务器以及宝塔面板快速搭建discuz论坛网站?

前面介绍了很多搭建个人网站&#xff0c;云网盘的方法&#xff0c;这篇文章将介绍使用discuz搭建一个论坛网站&#xff0c;采用的方式为轻量应用服务器搭配宝塔面板一键式部署discuz论坛网站&#xff0c;感兴趣的小伙伴可以跟着我一起搭建起来&#xff01; 说明&#xff1a; 云…

无线传感器网络:数据链路层,MAC

文章目录FramingByte CountFlag Byte MethodByte StuffingMedium Access Control (MAC)Static Channel AllocationDynamic Channel AllocationIndependent TrafficSingle ChannelObservable CollisionsContinuous or Slotted TimeCarrier Sense or No Carrier SensePure ALOHAS…

react的useState源码分析

前言 简单说下为什么React选择函数式组件&#xff0c;主要是class组件比较冗余、生命周期函数写法不友好&#xff0c;骚写法多&#xff0c;functional组件更符合React编程思想等等等。更具体的可以拜读dan大神的blog。其中Function components capture the rendered values这句…

JWT有状态登陆与无状态登陆

单点登录与JWT JWT 全称&#xff1a; Json Web Token 。作用&#xff1a; JWT 的作用是 用户授权(Authorization) &#xff0c;而不是用户的身份认证(Authentication) 。用户认证 指的是使用用户名、密码来验证当前用户的身份&#xff0c;即用户登录。用户授权 指用户登录成功后…

「从零单排canal 07」 parser模块源码解析

本文将对canal的binlog订阅模块parser进行分析。 parser模块(绿色部分)在整个系统中的角色如下图所示&#xff0c;用来订阅binlog事件&#xff0c;然后通过sink投递到store. parser模块应该来说是整个项目里面比较复杂的模块&#xff0c;代码非常多。 因此&#xff0c;本文根…

Nmap爆破MySQL弱口令漏洞:解决报错Accounts: No valid accounts found

nmap工具不仅仅能扫描&#xff0c;也可以暴力破解mysql&#xff0c;ftp&#xff0c;telnet等服务。 看到这里不要怀疑&#xff0c;在kali系统中查一下到底支持哪些暴力破解功能&#xff0c;命令如下 ls /usr/share/nmap/scripts |grep brute.nse 查询结果为 afp-brute.nse …

镜像底层原理详解和基于Docker file创建镜像

目录 一、镜像底层原理 1.联合文件系统(UnionFS) 2.镜像加载原理 3.为什么Docker里的centos的大小才200M? 二、Dockerfile 1.简介 2.Dockerfile操作常用命令 &#xff08;1&#xff09;FORM 镜像 &#xff08;2&#xff09;MAINTAINER 维护人信息 &#xff08;3&…

Vue的devtools安装教程

devtools是一个便于开发者调试Vue代码的插件 先确保你已经安装了node.js 点击此处去github上拉取工具包 安装yarn&#xff08;用npm在打包的时候会失败&#xff0c;使用yarn可以打包成功&#xff09; ① cmd输入&#xff1a;npm install -g yarn 全局安装yarn包管理工具   …

Nature Plants|植物基因组测序20年回顾与展望:三代HiFi基因组时代

2021年11月29日&#xff0c;美国密歇根州立大学在《Nature Plants》期刊在线发表题为“Representation and participation across 20 years of plant genomesequencing”综述&#xff0c;系统阐述了在过去的20年间&#xff0c;对陆地植物基因组学组装质量、已测序物种的分类和地…