在复杂场景下,希望一个生产者生产的数据放入RingBuffer后,能够被多个消费者消费,至于消费的方式,可能各有不同,比如菱形结构、六边形结构、顺序执行。接下来我们一一介绍
菱形结构:
说明:P1生产的数据给C1和C2并行执行完成后,再交给C3执行。
代码:
Handler1:设置了事先名称h1
import com.lmax.disruptor.EventHandler;
import com.lmax.disruptor.WorkHandler;
import jeff.generate1.Trade;
public class Handler1 implements EventHandler<Trade>,WorkHandler<Trade> {
@Override
public void onEvent(Trade event, long sequence, boolean endOfBatch) throws Exception {
this.onEvent(event);
}
@Override
public void onEvent(Trade event) throws Exception {
System.out.println("handler1: set name"+"----price:"+event.getPrice());
event.setName("h1");
Thread.sleep(1000);
}
}
Handler2:设置了事件价格17.0
import com.lmax.disruptor.EventHandler;
import jeff.generate1.Trade;
public class Handler2 implements EventHandler<Trade> {
@Override
public void onEvent(Trade event, long sequence, boolean endOfBatch) throws Exception {
System.out.println("handler2: set price"+"----price:"+event.getPrice());
event.setPrice(17.0);
Thread.sleep(1000);
}
}
Handler3:打印了事件的名称、价格及实例
import com.lmax.disruptor.EventHandler;
import jeff.generate1.Trade;
public class Handler3 implements EventHandler<Trade> {
@Override
public void onEvent(Trade event, long sequence, boolean endOfBatch) throws Exception {
System.out.println("handler3: name: " + event.getName() + " , price: " + event.getPrice() + "; instance: " + event.toString());
}
}
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.lmax.disruptor.BusySpinWaitStrategy;
import com.lmax.disruptor.EventFactory;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.EventHandlerGroup;
import com.lmax.disruptor.dsl.ProducerType;
import jeff.generate1.Trade;
public class Main {
public static void main(String[] args) throws InterruptedException {
long beginTime=System.currentTimeMillis();
int bufferSize=1024;
ExecutorService executor=Executors.newFixedThreadPool(8);
Disruptor<Trade> disruptor = new Disruptor<Trade>(new EventFactory<Trade>() {
@Override
public Trade newInstance() {
return new Trade();
} //指定一个生产者
}, bufferSize, executor, ProducerType.SINGLE, new BusySpinWaitStrategy());
//菱形操作
//handleEventsWith:使用disruptor创建消费者组C1,C2 并行执行
EventHandlerGroup<Trade> handlerGroup =
disruptor.handleEventsWith(new Handler1(), new Handler2());
//声明在C1,C2完事之后执行JMS消息发送操作 也就是流程走到C3
handlerGroup.then(new Handler3());
disruptor.start();//启动
CountDownLatch latch=new CountDownLatch(1);
//生产者准备
executor.submit(new TradePublisher(latch, disruptor));
latch.await();//等待生产者完事.
disruptor.shutdown();
executor.shutdown();
System.out.println("总耗时:"+(System.currentTimeMillis()-beginTime));
}
}
解释下上边生产者代码片段:
//生产者准备
executor.submit(new TradePublisher(latch, disruptor));
在线程池中提交了生产者处理线程实现了Runnable接口:
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import com.lmax.disruptor.EventTranslator;
import com.lmax.disruptor.dsl.Disruptor;
import jeff.generate1.Trade;
public class TradePublisher implements Runnable {
Disruptor<Trade> disruptor;
private CountDownLatch latch;
private static int LOOP=1;
public TradePublisher(CountDownLatch latch,Disruptor<Trade> disruptor) {
this.disruptor=disruptor;
this.latch=latch;
}
@Override
public void run() {
TradeEventTranslator tradeTransloator = new TradeEventTranslator();
//disruptor发布1个数据并填充
for(int i=0;i<LOOP;i++){
disruptor.publishEvent(tradeTransloator);
}
latch.countDown();
}
}
class TradeEventTranslator implements EventTranslator<Trade>{
private Random random=new Random();
@Override
public void translateTo(Trade event, long sequence) {
this.generateTrade(event);
}
private Trade generateTrade(Trade trade){
trade.setPrice(random.nextDouble()*9999);
return trade;
}
}
在TradePublisher的run方法中:
disruptor.publishEvent(tradeTransloator);
我们向discruptor中发布了一个事件初始化器TradeEventTranslator实现了EventTranslator接口,类型为Trade。在这个事件初始化器中给trade对象设置了随机价格,translateTo方法的执行会触发,Handler1和Handler2的执行,以及之后Handler3的执行。
再看下消费者菱形执行消费代码:
EventHandlerGroup<Trade> handlerGroup =
disruptor.handleEventsWith(new Handler1(), new Handler2());
//声明在C1,C2完事之后执行JMS消息发送操作 也就是流程走到C3
handlerGroup.then(new Handler3());
handleEventsWith这个方法中提交了Handler1和Handler2两个实例,组成了消费者组handlerGroup,然后handlerGroup使用then方法提交了Handler3,表示在Handler1和Handler2两个实例并行执行完成后,再执行Handler3操作。
打印:
handler1: set name----price:6333.697550972724
handler2: set price----price:6333.697550972724
handler3: name: h1 , price: 17.0; instance: jeff.generate1.Trade@71f111ba
总耗时:18376
注意理解:例子中只生产了一个数据,Handler1和Handler2包括Handler3在内,都执行的是同一个Trade对象,可以从上边的打印看出来,Handler1和Handler2的price数据就是translateTo方法中设置的那个随机数。
六边形结构
Handler1 h1 = new Handler1();
Handler2 h2 = new Handler2();
Handler3 h3 = new Handler3();
Handler4 h4 = new Handler4();
Handler5 h5 = new Handler5();
disruptor.handleEventsWith(h1, h2);
disruptor.after(h1).handleEventsWith(h4);
disruptor.after(h2).handleEventsWith(h5);
disruptor.after(h4, h5).handleEventsWith(h3);
图解:
说明:P1生产的数据,被(h1,h4)和(h2,h5)并行执行完成后,h3再执行。对于(h1,h4)和(h2,h5),h1执行后h4再执行;h2执行后h5再执行。
Handler4:
import com.lmax.disruptor.EventHandler;
import com.lmax.disruptor.WorkHandler;
import jeff.generate1.Trade;
public class Handler4 implements EventHandler<Trade>,WorkHandler<Trade> {
@Override
public void onEvent(Trade event, long sequence, boolean endOfBatch) throws Exception {
this.onEvent(event);
}
@Override
public void onEvent(Trade event) throws Exception {
System.out.println("handler4: get name : " + event.getName());
event.setName(event.getName() + "h4");
}
}
import com.lmax.disruptor.EventHandler;
import com.lmax.disruptor.WorkHandler;
import jeff.generate1.Trade;
public class Handler5 implements EventHandler<Trade>,WorkHandler<Trade> {
@Override
public void onEvent(Trade event, long sequence, boolean endOfBatch) throws Exception {
this.onEvent(event);
}
@Override
public void onEvent(Trade event) throws Exception {
System.out.println("handler5: get price : " + event.getPrice());
event.setPrice(event.getPrice() + 3.0);
}
}
打印:
handler2: set price----price:2172.612895685139
handler1: set name----price:17.0
handler5: get price : 17.0
handler4: get name : h1
handler3: name: h1h4 , price: 20.0; instance: jeff.generate1.Trade@363bed68
总耗时:1119
分析:handler2设置了price为17.0,那么h5得到一定是17.0;h1设置了name为h1后,h4一定得到的是h1。
最后handler3得到的name一定是h1h4,得到的price一定是20.0。它们处理的都是同一个实例trade。
顺序执行:
disruptor.handleEventsWith(new Handler1()).
handleEventsWith(new Handler2()).
handleEventsWith(new Handler3());
图解:
打印:
handler1: set name----price:1405.3587126200412
handler2: set price----price:1405.3587126200412
handler3: name: h1 , price: 17.0; instance: jeff.generate1.Trade@74ee7e66
总耗时:2056