今天用一个停车场问题来加深对Disruptor的理解。一个有关汽车进入停车场的问题。当汽车进入停车场时,系统首先会记录汽车信息。同时也会发送消息到其他系统处理相关业务,最后发送短信通知车主收费开始。看了很多文章,里面的代码都是大同小异的,可能代码真的是很经典。以下代码也是来源网络,只是自己手动敲的,加了一些注释。
 
代码包含以下内容:
1) 事件对象Event
2)三个消费者Handler
3)一个生产者Processer
4)执行Main方法
Event类:汽车信息
  1.  
    public class MyInParkingDataEvent {
  2.  
     
  3.  
    private String carLicense; // 车牌号
  4.  
     
  5.  
    public String getCarLicense() {
  6.  
    return carLicense;
  7.  
    }
  8.  
     
  9.  
    public void setCarLicense(String carLicense) {
  10.  
    this.carLicense = carLicense;
  11.  
    }
  12.  
     
  13.  
    }

Handler类:一个负责存储汽车数据,一个负责发送kafka信息到其他系统中,最后一个负责给车主发短信通知

  1.  
    import com.lmax.disruptor.EventHandler;
  2.  
    import com.lmax.disruptor.WorkHandler;
  3.  
     
  4.  
    /**
  5.  
    * Handler 第一个消费者,负责保存进场汽车的信息
  6.  
    *
  7.  
    */
  8.  
    public class MyParkingDataInDbHandler implements EventHandler<MyInParkingDataEvent> , WorkHandler<MyInParkingDataEvent>{
  9.  
     
  10.  
    @Override
  11.  
    public void onEvent(MyInParkingDataEvent myInParkingDataEvent) throws Exception {
  12.  
    long threadId = Thread.currentThread().getId(); // 获取当前线程id
  13.  
    String carLicense = myInParkingDataEvent.getCarLicense(); // 获取车牌号
  14.  
    System.out.println(String.format("Thread Id %s 保存 %s 到数据库中 ....", threadId, carLicense));
  15.  
    }
  16.  
     
  17.  
    @Override
  18.  
    public void onEvent(MyInParkingDataEvent myInParkingDataEvent, long sequence, boolean endOfBatch)
  19.  
    throws Exception {
  20.  
    this.onEvent(myInParkingDataEvent);
  21.  
    }
  22.  
     
  23.  
    }
  1.  
    import com.lmax.disruptor.EventHandler;
  2.  
     
  3.  
    /**
  4.  
    * 第二个消费者,负责发送通知告知工作人员(Kafka是一种高吞吐量的分布式发布订阅消息系统)
  5.  
    */
  6.  
    public class MyParkingDataToKafkaHandler implements EventHandler<MyInParkingDataEvent>{
  7.  
     
  8.  
    @Override
  9.  
    public void onEvent(MyInParkingDataEvent myInParkingDataEvent, long sequence, boolean endOfBatch)
  10.  
    throws Exception {
  11.  
    long threadId = Thread.currentThread().getId(); // 获取当前线程id
  12.  
    String carLicense = myInParkingDataEvent.getCarLicense(); // 获取车牌号
  13.  
    System.out.println(String.format("Thread Id %s 发送 %s 进入停车场信息给 kafka系统...", threadId, carLicense));
  14.  
    }
  15.  
     
  16.  
    }
  1.  
    import com.lmax.disruptor.EventHandler;
  2.  
     
  3.  
    /**
  4.  
    * 第三个消费者,sms短信服务,告知司机你已经进入停车场,计费开始。
  5.  
    */
  6.  
    public class MyParkingDataSmsHandler implements EventHandler<MyInParkingDataEvent>{
  7.  
     
  8.  
    @Override
  9.  
    public void onEvent(MyInParkingDataEvent myInParkingDataEvent, long sequence, boolean endOfBatch)
  10.  
    throws Exception {
  11.  
    long threadId = Thread.currentThread().getId(); // 获取当前线程id
  12.  
    String carLicense = myInParkingDataEvent.getCarLicense(); // 获取车牌号
  13.  
    System.out.println(String.format("Thread Id %s 给 %s 的车主发送一条短信,并告知他计费开始了 ....", threadId, carLicense));
  14.  
    }
  15.  
     
  16.  
    }

Producer类:负责上报停车数据

  1.  
    import java.util.concurrent.CountDownLatch;
  2.  
    import com.lmax.disruptor.EventTranslator;
  3.  
    import com.lmax.disruptor.dsl.Disruptor;
  4.  
     
  5.  
    /**
  6.  
    * 生产者,进入停车场的车辆
  7.  
    */
  8.  
    public class MyInParkingDataEventPublisher implements Runnable{
  9.  
     
  10.  
    private CountDownLatch countDownLatch; // 用于监听初始化操作,等初始化执行完毕后,通知主线程继续工作
  11.  
    private Disruptor<MyInParkingDataEvent> disruptor;
  12.  
    private static final Integer NUM = 1; // 1,10,100,1000
  13.  
     
  14.  
    public MyInParkingDataEventPublisher(CountDownLatch countDownLatch,
  15.  
    Disruptor<MyInParkingDataEvent> disruptor) {
  16.  
    this.countDownLatch = countDownLatch;
  17.  
    this.disruptor = disruptor;
  18.  
    }
  19.  
     
  20.  
    @Override
  21.  
    public void run() {
  22.  
    MyInParkingDataEventTranslator eventTranslator = new MyInParkingDataEventTranslator();
  23.  
    try {
  24.  
    for(int i = 0; i < NUM; i ++) {
  25.  
    disruptor.publishEvent(eventTranslator);
  26.  
    Thread.sleep(1000); // 假设一秒钟进一辆车
  27.  
    }
  28.  
    } catch (InterruptedException e) {
  29.  
    e.printStackTrace();
  30.  
    } finally {
  31.  
    countDownLatch.countDown(); // 执行完毕后通知 await()方法
  32.  
    System.out.println(NUM + "辆车已经全部进入进入停车场!");
  33.  
    }
  34.  
    }
  35.  
     
  36.  
    }
  37.  
     
  38.  
    class MyInParkingDataEventTranslator implements EventTranslator<MyInParkingDataEvent> {
  39.  
     
  40.  
    @Override
  41.  
    public void translateTo(MyInParkingDataEvent myInParkingDataEvent, long sequence) {
  42.  
    this.generateData(myInParkingDataEvent);
  43.  
    }
  44.  
     
  45.  
    private MyInParkingDataEvent generateData(MyInParkingDataEvent myInParkingDataEvent) {
  46.  
    myInParkingDataEvent.setCarLicense("车牌号: 鄂A-" + (int)(Math.random() * 100000)); // 随机生成一个车牌号
  47.  
    System.out.println("Thread Id " + Thread.currentThread().getId() + " 写完一个event");
  48.  
    return myInParkingDataEvent;
  49.  
    }
  50.  
     
  51.  
    }

执行的Main方法:

  1.  
    import com.lmax.disruptor.EventFactory;
  2.  
    import com.lmax.disruptor.YieldingWaitStrategy;
  3.  
    import com.lmax.disruptor.dsl.Disruptor;
  4.  
    import com.lmax.disruptor.dsl.EventHandlerGroup;
  5.  
    import com.lmax.disruptor.dsl.ProducerType;
  6.  
     
  7.  
    /**
  8.  
    * 执行的Main方法 ,
  9.  
    * 一个生产者(汽车进入停车场);
  10.  
    * 三个消费者(一个记录汽车信息,一个发送消息给系统,一个发送消息告知司机)
  11.  
    * 前两个消费者同步执行,都有结果了再执行第三个消费者
  12.  
    */
  13.  
    public class MyInParkingDataEventMain {
  14.  
     
  15.  
    public static void main(String[] args) {
  16.  
    long beginTime=System.currentTimeMillis();
  17.  
    int bufferSize = 2048; // 2的N次方
  18.  
    try {
  19.  
    // 创建线程池,负责处理Disruptor的四个消费者
  20.  
    ExecutorService executor = Executors.newFixedThreadPool(4);
  21.  
     
  22.  
    // 初始化一个 Disruptor
  23.  
    Disruptor<MyInParkingDataEvent> disruptor = new Disruptor<MyInParkingDataEvent>(new EventFactory<MyInParkingDataEvent>() {
  24.  
    @Override
  25.  
    public MyInParkingDataEvent newInstance() {
  26.  
    return new MyInParkingDataEvent(); // Event 初始化工厂
  27.  
    }
  28.  
    }, bufferSize, executor, ProducerType.SINGLE, new YieldingWaitStrategy());
  29.  
     
  30.  
    // 使用disruptor创建消费者组 MyParkingDataInDbHandler 和 MyParkingDataToKafkaHandler
  31.  
    EventHandlerGroup<MyInParkingDataEvent> handlerGroup = disruptor.handleEventsWith(
  32.  
    new MyParkingDataInDbHandler(), new MyParkingDataToKafkaHandler());
  33.  
     
  34.  
    // 当上面两个消费者处理结束后在消耗 smsHandler
  35.  
    MyParkingDataSmsHandler myParkingDataSmsHandler = new MyParkingDataSmsHandler();
  36.  
    handlerGroup.then(myParkingDataSmsHandler);
  37.  
     
  38.  
    // 启动Disruptor
  39.  
    disruptor.start();
  40.  
     
  41.  
    CountDownLatch countDownLatch = new CountDownLatch(1); // 一个生产者线程准备好了就可以通知主线程继续工作了
  42.  
    // 生产者生成数据
  43.  
    executor.submit(new MyInParkingDataEventPublisher(countDownLatch, disruptor));
  44.  
    countDownLatch.await(); // 等待生产者结束
  45.  
     
  46.  
    disruptor.shutdown();
  47.  
    executor.shutdown();
  48.  
    } catch (Exception e) {
  49.  
    e.printStackTrace();
  50.  
    }
  51.  
     
  52.  
    System.out.println("总耗时:"+(System.currentTimeMillis()-beginTime));
  53.  
    }
  54.  
     
  55.  
    }

--------------------- 本文来自 ITDragon龙 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/qq_19558705/article/details/77247912?utm_source=copy

并发框架Disruptor场景应用的更多相关文章

  1. 无锁并发框架Disruptor学习入门

    刚刚听说disruptor,大概理一下,只为方便自己理解,文末是一些自己认为比较好的博文,如果有需要的同学可以参考. 本文目标:快速了解Disruptor是什么,主要概念,怎么用 1.Disrupto ...

  2. 并发框架Disruptor译文

    Martin Fowler在自己网站上写了一篇LMAX架构的文章,在文章中他介绍了LMAX是一种新型零售金融交易平台,它能够以很低的延迟产生大量交易.这个系统是建立在JVM平台上,其核心是一个业务逻辑 ...

  3. 并发框架Disruptor浅析

    1.引言 Disruptor是一个开源的Java框架,它被设计用于在生产者—消费者(producer-consumer problem,简称PCP)问题上获得尽量高的吞吐量(TPS)和尽量低的延迟.D ...

  4. Java 并发框架Disruptor(七)

    Disruptor VS BlockingQueue的压测对比: import java.util.concurrent.ArrayBlockingQueue; public class ArrayB ...

  5. Disruptor并发框架(一)简介&上手demo

    框架简介 Martin Fowler在自己网站上写了一篇LMAX架构的文章,在文章中他介绍了LMAX是一种新型零售金融交易平台,它能够以很低的延迟产生大量交易.这个系统是建立在JVM平台上,其核心是一 ...

  6. 并发编程之Disruptor并发框架

    一.什么是Disruptor Martin Fowler在自己网站上写了一篇LMAX架构的文章,在文章中他介绍了LMAX是一种新型零售金融交易平台,它能够以很低的延迟产生大量交易.这个系统是建立在JV ...

  7. Disruptor 并发框架

    什么是Disruptor Martin Fowler在自己网站上写了一篇LMAX架构的文章,在文章中他介绍了LMAX是一种新型零售金融交易平台,它能够以很低的延迟产生大量交易.这个系统是建立在JVM平 ...

  8. Disruptor并发框架简介

    Martin Fowler在自己网站上写一篇LMAX架构的文章,在文章中他介绍了LMAX是一种新型零售金额交易平台,它能够以很低的延迟产生大量交易.这个系统是建立在JVM平台上,其核心是一个业务逻辑处 ...

  9. 来,带你鸟瞰 Java 中4款常用的并发框架!

    1. 为什么要写这篇文章 几年前 NoSQL 开始流行的时候,像其他团队一样,我们的团队也热衷于令人兴奋的新东西,并且计划替换一个应用程序的数据库. 但是,当深入实现细节时,我们想起了一位智者曾经说过 ...

随机推荐

  1. 爬虫入门(四)——Scrapy框架入门:使用Scrapy框架爬取全书网小说数据

    为了入门scrapy框架,昨天写了一个爬取静态小说网站的小程序 下面我们尝试爬取全书网中网游动漫类小说的书籍信息. 一.准备阶段 明确一下爬虫页面分析的思路: 对于书籍列表页:我们需要知道打开单本书籍 ...

  2. Chapter 5 Blood Type——28

    Mike came through the door then, glancing from me to Edward. 然后Mike从门里走出来,看了一眼我和Edward The look he g ...

  3. Spring Boot分布式系统实践【扩展1】shiro+redis实现session共享、simplesession反序列化失败的问题定位及反思改进

    前言 调试之前请先关闭Favicon配置 spring:     favicon:       enabled: false 不然会发现有2个请求(如果用nginx+ 浏览器调试的话) 序列化工具类[ ...

  4. SVN就是这么简单

    什么是SVN SVN全称:Subversion,是一个开放源代码的版本控制系统 Svn是一种集中式文件版本管理系统.集中式代码管理的核心是服务器,所有开发者在开始新一天的工作之前必须从服务器获取代码, ...

  5. gcc编译基本用法~2

    编译简单的 C 程序 C 语言经典的入门例子是 Hello World,下面是一示例代码: ;} 我们假定该代码存为文件‘hello.c’.要用 gcc 编译该文件,使用下面的命令: $ gcc -g ...

  6. LeetCode专题-Python实现之第1题:Two Sum

    导航页-LeetCode专题-Python实现 相关代码已经上传到github:https://github.com/exploitht/leetcode-python 文中代码为了不动官网提供的初始 ...

  7. ES6躬行记(16)——Set

    ES6引入了两种新的数据结构:Set和Map.Set是一组值的集合,其中值不能重复:Map(也叫字典)是一组键值对的集合,其中键不能重复.Set和Map都由哈希表(Hash Table)实现,并可按添 ...

  8. [二十六]JavaIO之再回首恍然(如梦? 大悟?)

    流分类回顾 本文是JavaIO告一段落的总结帖 希望对JavaIO做一个基础性的总结(不涉及NIO) 从实现的角度进行简单的介绍 下面的这两个表格,之前出现过 数据源形式 InputStream Ou ...

  9. 痞子衡嵌入式:ARM Cortex-M文件那些事(6)- 可执行文件(.out/.elf)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家讲的是嵌入式开发里的executable文件(elf). 第四.五节课里,痞子衡已经给大家介绍了2种output文件,本文继续给大家讲proje ...

  10. [转]Gitlab-CI持续集成之Runner配置和CI脚本

    本文转自:https://www.cnblogs.com/jiukun/p/7481287.html 一.简介 1. 为实现持续集成,需为该项目准备以下两样东西: 1)软件集成脚本.(gitlab-c ...