上一篇只是介绍了disruptor的核心概念,并举例了单消费单生产,本文将介绍各种消费类型
@Data
public class Trade {
private String id;
private String name;
private double price;
private AtomicInteger count = new AtomicInteger(0);
}
public class TradePublisher implements Runnable {
private Disruptor disruptor;
private CountDownLatch latch;
private static int PUBLISH_COUNT = 1;
public TradePublisher(CountDownLatch latch, Disruptor disruptor) {
this.disruptor = disruptor;
this.latch = latch;
}
/**
* When an object implementing interface Runnable
is used
* to create a thread, starting the thread causes the object's
* run
method to be called in that separately executing
* thread.
*
* The general contract of the method run
is that it may
* take any action whatsoever.
*
* @see Thread#run()
*/
@Override
public void run() {
TradeEventTranslator eventTranslator = new TradeEventTranslator();
for(int i=0; i{
private Random random = new Random();
@Override
public void translateTo(Trade event, long sequence) {
this.generateTrade(event);
}
private void generateTrade(Trade event) {
event.setPrice(random.nextDouble() *9999);
}
}
}
消费者1
public class Handler1 implements EventHandler , WorkHandler {
// EventHandler
@Override
public void onEvent(Trade trade, long sequence, boolean endOfBatch) throws Exception {
this.onEvent(trade);
}
// WorkHandler
@Override
public void onEvent(Trade trade) throws Exception {
System.err.println("handler 1 : SET NAME");
trade.setName("H1");
Thread.sleep(1000);
}
}
消费者2
public class Handler2 implements EventHandler {
@Override
public void onEvent(Trade trade, long sequence, boolean endOfBatch) throws Exception {
System.err.println("handler 2 : SET ID");
trade.setId(UUID.randomUUID().toString());
Thread.sleep(2000);
}
}
消费者3
public class Handler3 implements EventHandler {
@Override
public void onEvent(Trade trade, long sequence, boolean endOfBatch) throws Exception {
System.err.println("handler 3 : NAME:"+ trade.getName()
+",ID:"+trade.getId() + ",INSTANCE:"+trade.toString());
}
}
消费者4
public class Handler4 implements EventHandler {
@Override
public void onEvent(Trade trade, long sequence, boolean endOfBatch) throws Exception {
System.err.println("handler 4 : SET PRICE");
trade.setPrice(17.0);
}
}
消费者5
public class Handler5 implements EventHandler {
@Override
public void onEvent(Trade trade, long sequence, boolean endOfBatch) throws Exception {
System.err.println("handler 5 : GET PRICE:" + trade.getPrice());
trade.setPrice(trade.getPrice() + 3.0);
}
}
package com.example.disruptor.height.chain;
import com.lmax.disruptor.BusySpinWaitStrategy;
import com.lmax.disruptor.EventFactory;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) throws InterruptedException {
// 构建一个线程池用于提交任务
ExecutorService executorService1 = Executors.newFixedThreadPool(4);
ExecutorService executorService2 = Executors.newFixedThreadPool(5);
// 参数准备工作
int ringBufferSize = 1024 * 1024;
// 线程
/**
* 1 eventFactory: 消息(event)工厂对象
* 2 ringBufferSize: 容器的长度
* 3 executorService:线程池(建议使用自定义线程池)RejectedExecutionHandler
* 4 ProducerType:单生产者还是多生产者
* 5 waitStrategy:等待策略
*/
// 1.实例化disruptor对象
Disruptor disruptor = new Disruptor(new EventFactory() {
@Override
public Trade newInstance() {
return new Trade();
}
},
ringBufferSize,
executorService2,
ProducerType.SINGLE,
new BusySpinWaitStrategy()
);
// 2.把消费者设置到Disruptor中handleEventsWith
// 2.1.串行操作
disruptor
.handleEventsWith(new Handler1())
.handleEventsWith(new Handler2())
.handleEventsWith(new Handler3());
// 3. 启动disruptor
RingBuffer ringBuffer = disruptor.start();
CountDownLatch latch = new CountDownLatch(1);
Long start = System.currentTimeMillis();
executorService1.submit(new TradePublisher(latch, disruptor));
// 进行向下执行
latch.await();
disruptor.shutdown();
executorService1.shutdown();
executorService2.shutdown();
Long end = System.currentTimeMillis();
System.out.println("总耗时" + (end - start));
}
}
执行结果
因为是串行,执行完1,之后是2,最后3打印会有所有的值
disruptor.handleEventsWith(new Handler1());
disruptor.handleEventsWith(new Handler2());
disruptor.handleEventsWith(new Handler3());
disruptor.handleEventsWith(new Handler1(),new Handler2(),new Handler3());
执行结果
由上面两种方式可以看出,并行操作,在执行完3之后并没有1、2执行的结果,导致id和名称都是null
/**
* h1 ->
* h3
* h2 ->
*/
disruptor.handleEventsWith(new Handler1(), new Handler2()).
handleEventsWith(new Handler3());
EventHandlerGroup eventHandlerGroup = disruptor.handleEventsWith(new Handler1(), new Handler2());
eventHandlerGroup.then(new Handler3());
执行结果
实际执行控制台会将1、2直接打印,最后执行完会打印3
/*
1.1. h1 -> h2
start 2.h3
1.2. h4 -> h5
*/
Handler1 h1 = new Handler1();
Handler2 h2 = new Handler2();
Handler3 h3 = new Handler3();
Handler4 h4 = new Handler4();
Handler5 h5 = new Handler5();
disruptor.handleEventsWith(h1, h4);
disruptor.after(h1).handleEventsWith(h2);
disruptor.after(h4).handleEventsWith(h5);
disruptor.after(h2, h5).handleEventsWith(h3);
执行结果
由上可以看出,不管是串行还是并行等,disruptor支持各种模式的,完全是可以应用到不同的业务场景中,这样节约了串行导致的消耗时间