今天用一个停车场问题来加深对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. Leetcode 137. 只出现一次的数字 II - 题解

    Leetcode 137. 只出现一次的数字 II - 题解 137. Single Number II 在线提交: https://leetcode.com/problems/single-numb ...

  2. C++版 - 剑指offer 面试题23:从上往下打印二叉树(二叉树的层次遍历BFS) 题解

    剑指offer  面试题23:从上往下打印二叉树 参与人数:4853  时间限制:1秒  空间限制:32768K 提交网址: http://www.nowcoder.com/practice/7fe2 ...

  3. 【朝花夕拾】Android性能篇之(二)Java内存分配

    前言        在内存方面,相比于C/C++程序员,咱们java系程序员算是比较幸运的,因为对于内存的分配和回收,都交给了JVM来处理了,而不需要手动在代码中去完成.有了虚拟机内存管理机制,也就不 ...

  4. Java基础3:深入理解String及包装类

    更多内容请关注微信公众号[Java技术江湖] 这是一位阿里 Java 工程师的技术小站,作者黄小斜,专注 Java 相关技术:SSM.SpringBoot.MySQL.分布式.中间件.集群.Linux ...

  5. Python多环境管理

    Python环境管理 什么是Anaconda Anaconda是专注于数据分析的Python发行版本,包含了conda.Python等190多个科学包及其依赖项.Anaconda通过管理工具包.开发环 ...

  6. Typora中的Markdown教程

    Tutorial of markdown in Typora 工欲善其事,必先利其器 如上所说,这里给大家安利一款高BIG的利器Typora,这是一款文艺青年(装逼)必备的用于编写markdown的打 ...

  7. springboot情操陶冶-web配置(一)

    承接前文springboot情操陶冶-@SpringBootApplication注解解析,在前文讲解的基础上依次看下web方面的相关配置 环境包依赖 在pom.xml文件中引入web依赖,炒鸡简单, ...

  8. Perl线程池

    Thread::Pool模块提供了Perl解释器线程的线程池,手册:https://metacpan.org/pod/Thread::Pool.

  9. Xamarin.Forms 开发资源集合(复制)

    复制:https://www.cnblogs.com/mschen/p/10199997.html 收集整理了下 Xamarin.Forms 的学习参考资料,分享给大家,稍后会不断补充: UI样式 S ...

  10. (摘)linux下yum安装redis以及使用

    1.yum install redis      --查看是否有redis   yum 源 2.yum install epel-release    --下载fedora的epel仓库 3.yum ...