使用Disruptor的几个代码演示
来源:互联网 发布:js实现气泡随机运动 编辑:程序博客网 时间:2024/05/29 02:14
原文链接:http://www.dubby.cn/detail.html?id=9052
代码地址:https://github.com/dubby1994/disruptor-demo
关于Disruptor的原理,实在是太过复杂,限于我水平有限,这里就不一一展开。如果读者有兴趣,可以去看他们的官方文档,代码库已迁移到GitHub,https://github.com/LMAX-Exchange/disruptor/wiki/Getting-Started,如果想看中文翻译,可以直接去看并发编程网,但是这个中文翻译时,版本较低,看的时候,部分术语,方法名,甚至类名都和新版的不太一致,阅读时请注意。在这里,仅仅给出几个实例代码。
1. 编码准备
1.1 版本依赖
<dependency> <groupId>com.lmax</groupId> <artifactId>disruptor</artifactId> <version>3.3.7</version></dependency>
1.2 Java版本
1.8
1.3 公用的一些类
定义的消息格式LongEvent.java
package cn.dubby.disruptor.wizard;/** * Created by teeyoung on 17/10/27. */public class LongEvent { private long value; public void set(long value) { this.value = value; } public long getValue() { return value; }}
把输入对象翻译成消息消息对象Translator.java
package cn.dubby.disruptor.wizard;import com.lmax.disruptor.EventTranslatorOneArg;import java.nio.ByteBuffer;/** * Created by teeyoung on 17/10/27. */class Translator implements EventTranslatorOneArg<LongEvent, ByteBuffer> { @Override public void translateTo(LongEvent event, long sequence, ByteBuffer data) { event.set(data.getLong(0)); }}
一个消息消费者LongEventHandler.java
package cn.dubby.disruptor.basic;import com.lmax.disruptor.EventHandler;/** * Created by teeyoung on 17/10/27. */public class LongEventHandler implements EventHandler<LongEvent> { public void onEvent(LongEvent event, long sequence, boolean endOfBatch) { System.out.println("Event: " + event.getValue()); }}
2. 简单示例
2.1 单生产者,单消费者
SingleProductorLongEventMain.java
package cn.dubby.disruptor.basic;import com.lmax.disruptor.BlockingWaitStrategy;import com.lmax.disruptor.RingBuffer;import com.lmax.disruptor.dsl.Disruptor;import com.lmax.disruptor.dsl.ProducerType;import java.nio.ByteBuffer;import java.util.concurrent.Executor;import java.util.concurrent.Executors;/** * Created by teeyoung on 17/10/27. */public class SingleProductorLongEventMain { private static final Translator TRANSLATOR = new Translator(); public static void main(String[] args) throws Exception { // Executor that will be used to construct new threads for consumers Executor executor = Executors.newCachedThreadPool(); // Specify the size of the ring buffer, must be power of 2. int bufferSize = 1024; // Construct the Disruptor Disruptor<LongEvent> disruptor = new Disruptor<LongEvent>(LongEvent::new, bufferSize, executor, ProducerType.SINGLE, new BlockingWaitStrategy()); // Connect the handler disruptor.handleEventsWith(new LongEventHandler()); // Start the Disruptor, starts all threads running disruptor.start(); // Get the ring buffer from the Disruptor to be used for publishing. RingBuffer<LongEvent> ringBuffer = disruptor.getRingBuffer(); ByteBuffer bb = ByteBuffer.allocate(8); for (long l = 0; l < 10; l++) { bb.putLong(0, l); ringBuffer.publishEvent(TRANSLATOR, bb); Thread.sleep(100); } }}
这里bufferSize
的解释是the size of the ring buffer, must be power of 2.
,也就是你所定义的ringbuffer的大小,必须是2的幂。
这里还需要注意的一个地方,那就是新版的Disruptor不建议我们使用Executor
,而使用ThreadFactory
代替。
可以简单的换成:
ThreadFactory threadFactory = new ThreadFactory() { private final AtomicInteger index = new AtomicInteger(1); @Override public Thread newThread(Runnable r) { return new Thread((ThreadGroup) null, r, "disruptor-thread-" + index.getAndIncrement()); }};Disruptor<LongEvent> disruptor = new Disruptor<LongEvent>(LongEvent::new, bufferSize, threadFactory, ProducerType.SINGLE, new BlockingWaitStrategy());
结果:
2.2 多生产者,单消费者
MultiProductorLongEventMain.java
package cn.dubby.disruptor.basic;import com.lmax.disruptor.BlockingWaitStrategy;import com.lmax.disruptor.RingBuffer;import com.lmax.disruptor.dsl.Disruptor;import com.lmax.disruptor.dsl.ProducerType;import java.nio.ByteBuffer;import java.util.concurrent.Executor;import java.util.concurrent.Executors;/** * Created by teeyoung on 17/10/27. */public class MultiProductorLongEventMain { private static final Translator TRANSLATOR = new Translator(); public static void main(String[] args) throws Exception { // Executor that will be used to construct new threads for consumers Executor executor = Executors.newCachedThreadPool(); // Specify the size of the ring buffer, must be power of 2. int bufferSize = 1024; // Construct the Disruptor Disruptor<LongEvent> disruptor = new Disruptor<LongEvent>(LongEvent::new, bufferSize, executor, ProducerType.MULTI, new BlockingWaitStrategy()); // Connect the handler disruptor.handleEventsWith(new LongEventHandler()); // Start the Disruptor, starts all threads running disruptor.start(); // Get the ring buffer from the Disruptor to be used for publishing. new Thread(){ @Override public void run() { RingBuffer<LongEvent> ringBuffer = disruptor.getRingBuffer(); ByteBuffer bb = ByteBuffer.allocate(8); for (long l = 0; l < 10; l++) { bb.putLong(0, l); ringBuffer.publishEvent(TRANSLATOR, bb); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); new Thread(){ @Override public void run() { RingBuffer<LongEvent> ringBuffer = disruptor.getRingBuffer(); ByteBuffer bb = ByteBuffer.allocate(8); for (long l = 10; l < 20; l++) { bb.putLong(0, l); ringBuffer.publishEvent(TRANSLATOR, bb); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); new Thread(){ @Override public void run() { RingBuffer<LongEvent> ringBuffer = disruptor.getRingBuffer(); ByteBuffer bb = ByteBuffer.allocate(8); for (long l = 20; l < 30; l++) { bb.putLong(0, l); ringBuffer.publishEvent(TRANSLATOR, bb); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); }}
这里使用三个线程同时生产。
结果:
3. 领域特定语言(DSL)
3.1 简单的消费者依赖关系
这张图的意思就是消费者3消费时,必须保证消费者1和消费者2已经完成对该消息的消费。举个例子,在处理实际的业务逻辑(C3)之前,需要校验数据(C1),以及将数据写入磁盘(C2)。
DisruptorWizardMain.java
package cn.dubby.disruptor.wizard;import com.lmax.disruptor.EventHandler;import com.lmax.disruptor.RingBuffer;import com.lmax.disruptor.dsl.Disruptor;import java.nio.ByteBuffer;import java.util.concurrent.Executor;import java.util.concurrent.Executors;/** * Created by teeyoung on 17/10/28. */public class DisruptorWizardMain { private static final Translator TRANSLATOR = new Translator(); public static void main(String[] args) throws InterruptedException { Executor executor = Executors.newCachedThreadPool(); int bufferSize = 1024; EventHandler handler1 = new EventHandler<LongEvent>() { @Override public void onEvent(LongEvent event, long sequence, boolean endOfBatch) throws Exception { System.out.println("handler1 : " + event.getValue()); } }; EventHandler handler2 = new EventHandler<LongEvent>() { @Override public void onEvent(LongEvent event, long sequence, boolean endOfBatch) throws Exception { System.out.println("handler2 : " + event.getValue()); } }; EventHandler handler3 = new EventHandler<LongEvent>() { @Override public void onEvent(LongEvent event, long sequence, boolean endOfBatch) throws Exception { System.out.println("handler3 : " + event.getValue() + " arrived. Handler1 and handler2 should have completed. Completed.\n"); } }; Disruptor<LongEvent> disruptor = new Disruptor<>(LongEvent::new, bufferSize, executor); disruptor.handleEventsWith(handler1, handler2).then(handler3); disruptor.start(); RingBuffer<LongEvent> ringBuffer = disruptor.getRingBuffer(); ByteBuffer bb = ByteBuffer.allocate(8); for (long l = 0; true; l++) { bb.putLong(0, l); ringBuffer.publishEvent(TRANSLATOR, bb); Thread.sleep(1000); } }}
这里主要关注disruptor.handleEventsWith(handler1, handler2).then(handler3);
定义了先让1和2消费,然后才能让2消费。
运行结果:
3.1 复杂的消费者依赖关系
这张图的意思就是消费者1b消费时,必须保证消费者1a已经完成对该消息的消费;消费者2b消费时,必须保证消费者2a已经完成对该消息的消费;消费者c3消费时,必须保证消费者1b和2b已经完成对该消息的消费。
DisruptorWizardMain2.java
package cn.dubby.disruptor.wizard;import com.lmax.disruptor.EventHandler;import com.lmax.disruptor.RingBuffer;import com.lmax.disruptor.dsl.Disruptor;import java.nio.ByteBuffer;import java.util.concurrent.Executor;import java.util.concurrent.Executors;/** * Created by teeyoung on 17/10/28. */public class DisruptorWizardMain2 { private static final Translator TRANSLATOR = new Translator(); public static void main(String[] args) throws InterruptedException { Executor executor = Executors.newCachedThreadPool(); int bufferSize = 1024; EventHandler h1a = new EventHandler<LongEvent>() { @Override public void onEvent(LongEvent event, long sequence, boolean endOfBatch) throws Exception { System.out.println("h1a : " + event.getValue()); } }; EventHandler h1b = new EventHandler<LongEvent>() { @Override public void onEvent(LongEvent event, long sequence, boolean endOfBatch) throws Exception { System.out.println("h1b : " + event.getValue() + " arrived. H1a should have completed. Completed."); } }; EventHandler h2a = new EventHandler<LongEvent>() { @Override public void onEvent(LongEvent event, long sequence, boolean endOfBatch) throws Exception { System.out.println("h2a : " + event.getValue()); } }; EventHandler h2b = new EventHandler<LongEvent>() { @Override public void onEvent(LongEvent event, long sequence, boolean endOfBatch) throws Exception { System.out.println("h2b : " + event.getValue() + " arrived. H2a should have completed. Completed."); } }; EventHandler lastHandler = new EventHandler<LongEvent>() { @Override public void onEvent(LongEvent event, long sequence, boolean endOfBatch) throws Exception { System.out.println("lastHandler : " + event.getValue() + " arrived. H1a, h1b, h2a and h2b should have completed. Completed.\n"); } }; Disruptor<LongEvent> disruptor = new Disruptor<>(LongEvent::new, bufferSize, executor); disruptor.handleEventsWith(h1a, h2a); disruptor.after(h1a).then(h1b); disruptor.after(h2a).then(h2b); disruptor.after(h1b, h2b).then(lastHandler); disruptor.start(); RingBuffer<LongEvent> ringBuffer = disruptor.getRingBuffer(); ByteBuffer bb = ByteBuffer.allocate(8); for (long l = 0; true; l++) { bb.putLong(0, l); ringBuffer.publishEvent(TRANSLATOR, bb); Thread.sleep(1000); } }}
其中主要关注
disruptor.handleEventsWith(h1a, h2a);disruptor.after(h1a).then(h1b);disruptor.after(h2a).then(h2b);disruptor.after(h1b, h2b).then(lastHandler);
这就是领域特定语言(DSL),定义了消费顺序。
结果:
微信扫码关注订阅号,获取更多精彩内容
- 使用Disruptor的几个代码演示
- Disruptor的使用
- Disruptor的使用
- disruptor的使用和分析
- Disruptor学习总结(一):Disruptor的使用
- 看过Disruptor代码之后的一些感想
- 高性能队列Disruptor的使用
- IOS-CoreData简单使用的主要代码<代码演示>
- Ext 的代码演示
- 并发框架Disruptor几个Demo
- 并发框架Disruptor几个Demo
- 使用系统托盘图标,显示 Balloon Tooltip 的 MASM32 演示代码
- 使用jsonp实现跨域访问的代码演示
- android几个使用的判定代码
- 使用grep搜索代码的几个示例
- Disruptor使用笔记
- Disruptor使用入门
- disruptor使用示例
- JDK动态代理
- fiddler网络抓包神器的使用介绍
- 递归 输出全排列
- java 类型转换
- 算法分析与设计课程作业第七周#1#2
- 使用Disruptor的几个代码演示
- 第七周 【项目6
- python3读取大文件的行数的正确姿势
- pyqt环境搭建安装
- 41、我的C#学习笔记7
- 中消协表示关注“携程搭售”,APP与网页端现区分搭售与否
- 亚马逊数据库意外泄露47GB医疗数据,波及15万患者
- 报名 | 科大讯飞(首届)全球1024开发者节,AI点亮未来!
- 戴尔正式进军物联网,计划砸金10亿美元