Disruptor多个消费者独立处理生产者消息的简单demo

来源:互联网 发布:高校教学软件代理 编辑:程序博客网 时间:2024/05/17 22:10

第一步:创建一个实体类用于封装对象:

package Disruptor;public class TradeTransaction { private String id;//交易ID      private double price;//交易金额            public TradeTransaction() {      }      public TradeTransaction(String id, double price) {          super();          this.id = id;          this.price = price;      }      public String getId() {          return id;      }      public void setId(String id) {          this.id = id;      }      public double getPrice() {          return price;      }      public void setPrice(double price) {          this.price = price;      }  }

第二步:分别创建3个消费者的实体类:

package Disruptor;import com.lmax.disruptor.EventHandler;public class TradeTransactionVasConsumer implements EventHandler<TradeTransaction>{//消费者C1接到消息后的业务处理逻辑@Overridepublic void onEvent(TradeTransaction arg0, long arg1, boolean arg2) throws Exception {// TODO Auto-generated method stub throws Exception {// do something....System.out.println("第一个消费者C1");}  }


package Disruptor;import java.util.UUID;import com.lmax.disruptor.EventHandler;import com.lmax.disruptor.WorkHandler;public class TradeTransactionInDBHandler implements EventHandler<TradeTransaction>,WorkHandler<TradeTransaction>{@Overridepublic void onEvent(TradeTransaction event) throws Exception {this.onEvent(event);}//消费者C2接到消息后的具体的业务 处理逻辑@Overridepublic void onEvent(TradeTransaction event, long arg1, boolean arg2) throws Exception { //这里做具体的消费业务逻辑,即就是接到消息后的业务处理逻辑       // event.setId(UUID.randomUUID().toString());//随机简单生成下ID 并且打印出来         System.out.println("第二个消费者C2消费了消息");  }}

package Disruptor;import com.lmax.disruptor.EventHandler;public class TradeTransactionJMSNotifyHandler implements EventHandler<TradeTransaction>{//消费者C3接到消息后的业务处理逻辑@Overridepublic void onEvent(TradeTransaction arg0, long arg1, boolean arg2) throws Exception {//do send jms message  System.out.println("最后一个消费者C3");}}


第 三步:创建一个生产者的实体类:


package Disruptor;import java.util.concurrent.CountDownLatch;import com.lmax.disruptor.dsl.Disruptor;//创建一个发送消费事件 的类,用于发送要处理的消息public class TradeTransactionPublisher implements Runnable {    Disruptor<TradeTransaction> disruptor;      private CountDownLatch latch;    private static int LOOP=10;//生产者发送10条消息         public TradeTransactionPublisher(CountDownLatch latch,Disruptor<TradeTransaction> disruptor) {          this.disruptor=disruptor;          this.latch=latch;      }    @Overridepublic void run() {// TODO Auto-generated method stubTradeTransactionEventTranslator tradeTransloator=new TradeTransactionEventTranslator();          for(int i=0;i<LOOP;i++){          System.out.println("生产者成功向Ringbuffer中发送了一条消息");            disruptor.publishEvent(tradeTransloator);          }          latch.countDown();      }  }

第四步:编写测试类如下

package Disruptor;import java.util.concurrent.CountDownLatch;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.ThreadFactory;import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;import com.lmax.disruptor.BusySpinWaitStrategy;import com.lmax.disruptor.EventFactory;import com.lmax.disruptor.LiteBlockingWaitStrategy;import com.lmax.disruptor.dsl.Disruptor;import com.lmax.disruptor.dsl.EventHandlerGroup;import com.lmax.disruptor.dsl.ProducerType;public class Demo3 {@SuppressWarnings("unchecked")public static void main(String[] args) throws InterruptedException {long beginTime = System.currentTimeMillis();//第一个参数用来在ring buffer中创建event,第二个参数是ring buffer的大小,第三个参数是消费者处理消息而使用的线程池。第四个参数是单或者多生产者模式,第五个参数是可选的等待策略。/*当消费者等待在SequenceBarrier上时,有许多可选的等待策略,不同的等待策略在延迟和CPU资源的占用上有所不同,可以视应用场景选择:BusySpinWaitStrategy : 自旋等待,类似Linux Kernel使用的自旋锁。低延迟但同时对CPU资源的占用也多。BlockingWaitStrategy : 使用锁和条件变量。CPU资源的占用少,延迟大。SleepingWaitStrategy : 在多次循环尝试不成功后,选择让出CPU,等待下次调度,多次调度后仍不成功,尝试前睡眠一个纳秒级别的时间再尝试。这种策略平衡了延迟和CPU资源占用,但延迟不均匀。YieldingWaitStrategy : 在多次循环尝试不成功后,选择让出CPU,等待下次调。平衡了延迟和CPU资源占用,但延迟也比较均匀。PhasedBackoffWaitStrategy : 上面多种策略的综合,CPU资源的占用少,延迟大。*///以上代码主要用来设置RingBuffer.int bufferSize = 1024;ExecutorService executor = Executors.newFixedThreadPool(4);ThreadFactory threadFactory = Executors.defaultThreadFactory();// @SuppressWarnings("deprecation")/*Disruptor<TradeTransaction> disruptor = new Disruptor<TradeTransaction>(new EventFactory<TradeTransaction>() {@Overridepublic TradeTransaction newInstance() {//参数叫EventFactory,事件工场,它的职责就是产生数据填充ringBuffer区return new TradeTransaction();}}, bufferSize, executor, ProducerType.SINGLE, new BusySpinWaitStrategy());*///我们只需要使用 Person::new 来获取Person类构造函数的引用,Java编译器会自动根据PersonFactory.create方法的签名来选择合适的构造函数。Disruptor<TradeTransaction> disruptor = new Disruptor<>(TradeTransaction::new, bufferSize, threadFactory,ProducerType.SINGLE, new LiteBlockingWaitStrategy());// 使用disruptor创建消费者组C1,C2TradeTransactionVasConsumer[] consumers = new TradeTransactionVasConsumer[2];for(int i =0;i<consumers.length;i++){consumers[i] = new TradeTransactionVasConsumer();}EventHandlerGroup<TradeTransaction> handlerGroup = disruptor.handleEventsWith(new TradeTransactionVasConsumer(),new TradeTransactionInDBHandler() );TradeTransactionJMSNotifyHandler jmsConsumer = new TradeTransactionJMSNotifyHandler();// 声明在C1,C2完事之后执行JMS消息发送操作 也就是流程走到C3handlerGroup.then(jmsConsumer);disruptor.start();// 启动CountDownLatch latch = new CountDownLatch(1);// 生产者准备executor.submit(new TradeTransactionPublisher(latch, disruptor));latch.await();// 等待生产者完事.disruptor.shutdown();executor.shutdown();System.out.println("总耗时:" + (System.currentTimeMillis() - beginTime));}}

发送了10条数据,打印结果如下:

生产者成功向Ringbuffer中发送了一条消息
生产者成功向Ringbuffer中发送了一条消息
第一个消费者C1
生产者成功向Ringbuffer中发送了一条消息
生产者成功向Ringbuffer中发送了一条消息
生产者成功向Ringbuffer中发送了一条消息
生产者成功向Ringbuffer中发送了一条消息
生产者成功向Ringbuffer中发送了一条消息
第一个消费者C1
第一个消费者C1
第一个消费者C1
第一个消费者C1
第一个消费者C1
第一个消费者C1
第二个消费者C2消费了消息
第二个消费者C2消费了消息
生产者成功向Ringbuffer中发送了一条消息
生产者成功向Ringbuffer中发送了一条消息
生产者成功向Ringbuffer中发送了一条消息
第二个消费者C2消费了消息
第二个消费者C2消费了消息
第二个消费者C2消费了消息
第二个消费者C2消费了消息
第二个消费者C2消费了消息
第二个消费者C2消费了消息
第二个消费者C2消费了消息
第二个消费者C2消费了消息
第一个消费者C1
第一个消费者C1
第一个消费者C1
最后一个消费者C3
最后一个消费者C3
最后一个消费者C3
最后一个消费者C3
最后一个消费者C3
最后一个消费者C3
最后一个消费者C3
最后一个消费者C3
最后一个消费者C3
最后一个消费者C3
总耗时:72

有结果可以看到,生产者一共发送了10条消息,消费者C1、C2、C3分别消费了这10条消息,并且C3是在C1和C2消费完消息后才消费的生产者发的消息

阅读全文
1 1