今天用一个停车场问题来加深对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. linux安装RabbitMQ

    一.RabbitMQ概念RabbitMQ是流行的开源消息队列系统,是AMQP(Advanced Message Queuing Protocol高级消息队列协议)的标准实现,用erlang语言开发.R ...

  2. Python爬虫入门教程 35-100 知乎网全站用户爬虫 scrapy

    爬前叨叨 全站爬虫有时候做起来其实比较容易,因为规则相对容易建立起来,只需要做好反爬就可以了,今天咱们爬取知乎.继续使用scrapy当然对于这个小需求来说,使用scrapy确实用了牛刀,不过毕竟本博客 ...

  3. 使用mpvue开发小程序教程(四)

    在上一章节中,我们将vue-cli命令行工具生成的代码骨架中的src目录清理了一遍,然后从头开始配置和编写了一个可以运行的小程序页面,算是正真走上了使用mpvue开发小程序的第一步.今天我们将进一步来 ...

  4. JDBC 连接池的两种方式——dbcp & c3p0

    申明:本文对于连接资源关闭采用自定义的 JDBCUtils 工具: package com.test.utils; import java.sql.Connection; import java.sq ...

  5. My操作小技巧

    1.当我们新增一条数据之后想要获取其自增长的id,可以紧随新增语句后调用 SELECT last_insert_id();即可获得,一般搭配变量一起使用 SELECT @newUserId:=last ...

  6. OO_BLOG1_简单表达式求导问题总结

    作业1-1 包含简单幂函数的多项式导函数的求解 I. 基于度量的程序结构分析 1)程序结构与基本度量统计图 2)分析 ​ 本人的第一次作业的程序实现逻辑十分简单,但是OOP的色彩并不强烈,程序耦合度过 ...

  7. php 关于经纬度距离计算方法

    1.PHP实现通过经纬度计算距离 单位为公里 function getdistance($lng1,$lat1,$lng2,$lat2)//根据经纬度计算距离 { //将角度转为狐度  $radLat ...

  8. Linux常见命令(一)

    三.常见linux命令: 命令提示符的解释: (1).组成(默认):[root@localhost~]# (2)[root@localhost~] root:系统当前登录账户名称,超级管理员为root ...

  9. 常用的String原型

    对于常用的字符串原型的举例 在字符串末尾追加字符串 String.prototype.append = function (str) { return this.concat(str);} 删除指定索 ...

  10. Dynamics 365 POA表记录的产生

    微软动态CRM专家罗勇 ,回复314或者20190311可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!我的网站是 www.luoyong.me . 前面的博文 Dyna ...