在helloWorld的实例中,我们创建Disruptor实例,然后调用getRingBuffer方法去获取RingBuffer,其实在很多时候,我们可以直接使用RingBuffer,以及其他的API操作。我们一起熟悉下示例:

使用EventProcessor消息处理器。

BatchEventProcessor 多线程并发执行,不同线程执行不同是不同的event

EventProcessor有3个实现类

BatchEventProcessor 多线程并发执行,不同线程执行不同是不同的event

使用BatchEventProcessor 消费者需要实现EventHandler接口

我们来看下面的代码:

需要处理的实体类

package bhz.generate1;

import java.util.concurrent.atomic.AtomicInteger;

public class Trade {  

    private String id;//ID
private String name;
private double price;//金额
private AtomicInteger count = new AtomicInteger(0); public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public AtomicInteger getCount() {
return count;
}
public void setCount(AtomicInteger count) {
this.count = count;
} }

消费者类:

package bhz.generate1;

import java.util.UUID;

import com.lmax.disruptor.EventHandler;
import com.lmax.disruptor.WorkHandler; public class TradeHandler 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 {
//杩欓噷鍋氬叿浣撶殑娑堣垂閫昏緫
event.setId(UUID.randomUUID().toString());//绠�崟鐢熸垚涓婭D
System.out.println(event.getId());
}
}

消费者除了实现EventHandler接口之外,还实现了WorkHandler接口,为啥了,因为后面我们要使用了WokerPool来发送该实体类,所以这里就让该实体类实现两个接口

我们来看看main方法

package bhz.generate1;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future; import com.lmax.disruptor.BatchEventProcessor;
import com.lmax.disruptor.EventFactory;
import com.lmax.disruptor.EventProcessor;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.SequenceBarrier;
import com.lmax.disruptor.YieldingWaitStrategy; public class Main1 { public static void main(String[] args) throws Exception {
int BUFFER_SIZE=1024;
int THREAD_NUMBERS=4;
/*
* createSingleProducer创建一个单生产者的RingBuffer,
* 第一个参数叫EventFactory,从名字上理解就是"事件工厂",其实它的职责就是产生数据填充RingBuffer的区块。
* 第二个参数是RingBuffer的大小,它必须是2的指数倍 目的是为了将求模运算转为&运算提高效率
* 第三个参数是RingBuffer的生产都在没有可用区块的时候(可能是消费者(或者说是事件处理器) 太慢了)的等待策略
*/
final RingBuffer<Trade> ringBuffer = RingBuffer.createSingleProducer(new EventFactory<Trade>() {
@Override
public Trade newInstance() {
return new Trade();
}
}, BUFFER_SIZE, new YieldingWaitStrategy()); //创建线程池
ExecutorService executors = Executors.newFixedThreadPool(THREAD_NUMBERS); //创建SequenceBarrier ,用于平衡生产者和消费者速率,用障碍来处理
SequenceBarrier sequenceBarrier = ringBuffer.newBarrier(); //创建消息处理器
BatchEventProcessor<Trade> transProcessor = new BatchEventProcessor<Trade>(
ringBuffer, sequenceBarrier, new TradeHandler()); //这一步的目的就是把消费者的位置信息引用注入到生产者 如果只有一个消费者的情况可以省略 ,将生产者和消费者关联起来
ringBuffer.addGatingSequences(transProcessor.getSequence()); //把消息处理器提交到线程池
executors.submit(transProcessor); //如果存在多个消费者 那重复执行上面3行代码 把TradeHandler换成其它消费者类 Future<?> future= executors.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
long seq;
for(int i=0;i<10;i++){
seq = ringBuffer.next();//占个坑 --ringBuffer一个可用区块
ringBuffer.get(seq).setPrice(Math.random()*9999);//给这个区块放入 数据
ringBuffer.publish(seq);//发布这个区块的数据使handler(consumer)可见
}
return null;
}
}); future.get();//等待生产者结束
Thread.sleep(1000);//等上1秒,等消费都处理完成
transProcessor.halt();//通知事件(或者说消息)处理器 可以结束了(并不是马上结束!!!)
executors.shutdown();//终止线程
}
}

//创建消息处理器
BatchEventProcessor<Trade> transProcessor = new BatchEventProcessor<Trade>(
ringBuffer, sequenceBarrier, new TradeHandler());

它主要有三个成员RingBuffer、SequenceBarrier和EventHandler

上面对应对应的是一个生产者,一个消费者的情况

我们来看看程序运行的效果

1a7226d0-e212-4183-b109-cab5e5c41545
3e1da0fa-686d-4361-bea2-600c2c5d26b9
bf31874a-3405-4008-80e7-03caf9f16ae4
080a05ef-0052-4271-a2ee-ee50038a5a77
71e1a5a8-24ba-4175-b53a-f8b71e99464a
99670de9-6aa5-48fa-8fa2-a490250e25ba
7a44b351-0caa-4ac3-b344-97cf72c9dd5f
10a7fe52-eef1-453c-80a2-126fd8bac948
c78f2ed5-3c3e-4481-9062-dd96ff7ba051
49f51ad6-2ee5-4c36-a0d0-96bc0e17fba9

如果是一个生产者,对应多个消费者,那么

//创建消息处理器
BatchEventProcessor<Trade> transProcessor = new BatchEventProcessor<Trade>(
ringBuffer, sequenceBarrier, new TradeHandler());

//这一步的目的就是把消费者的位置信息引用注入到生产者 如果只有一个消费者的情况可以省略 ,将生产者和消费者关联起来
ringBuffer.addGatingSequences(transProcessor.getSequence());

//把消息处理器提交到线程池
executors.submit(transProcessor);

//如果存在多个消费者 那重复执行上面3行代码 把TradeHandler换成其它消费者类

所以:BatchEventProcessor 多线程并发执行,不同线程执行不同是不同的event

2、使用WorkerPool消息处理器。

消费者需要实现:WorkHandler接口

我们来看看主程序的代码:

package bhz.generate1;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import com.lmax.disruptor.EventFactory;
import com.lmax.disruptor.IgnoreExceptionHandler;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.SequenceBarrier;
import com.lmax.disruptor.WorkHandler;
import com.lmax.disruptor.WorkerPool; public class Main2 {
public static void main(String[] args) throws InterruptedException {
int BUFFER_SIZE=1024;
int THREAD_NUMBERS=4; EventFactory<Trade> eventFactory = new EventFactory<Trade>() {
public Trade newInstance() {
return new Trade();
}
}; RingBuffer<Trade> ringBuffer = RingBuffer.createSingleProducer(eventFactory, BUFFER_SIZE); SequenceBarrier sequenceBarrier = ringBuffer.newBarrier(); ExecutorService executor = Executors.newFixedThreadPool(THREAD_NUMBERS); WorkHandler<Trade> handler = new TradeHandler(); WorkerPool<Trade> workerPool = new WorkerPool<Trade>(ringBuffer, sequenceBarrier, new IgnoreExceptionHandler(), handler); workerPool.start(executor); //下面这个生产8个数据
for(int i=0;i<8;i++){
long seq=ringBuffer.next();
ringBuffer.get(seq).setPrice(Math.random()*9999);
ringBuffer.publish(seq);
}
Thread.sleep(1000);
workerPool.halt();
executor.shutdown();
}
}

程序运行的效果:

4bbffa55-b19f-44a4-bfa7-100affc63323
121a0ee8-7e8e-4637-b659-ca78ae9aaa20
0fc1cdb8-8186-44fc-a3a5-4bf5fea66086
afb70a80-e1ce-46f9-bfc1-4e0d81be96b4
0e0b3690-830b-4d38-b78b-e0930b499515
f5b4e23f-10c8-45ea-b064-32ae40f54912
4a172494-480a-4509-99d0-d416b5e2c5c9
902c0669-6196-423e-9924-31cb9633bbb5

disruptor架构三 使用场景 使用WorkHandler和BatchEventProcessor辅助创建消费者的更多相关文章

  1. disruptor架构三 使用场景更加复杂的场景

    先c1和c2并行消费生产者产生的数据,然后c3再消费该数据 我们来使用代码实现:我们可以使用Disruptor实例来实现,也可以不用产生Disruptor实例,直接调用RingBuffer的api来实 ...

  2. disruptor架构四 多生产者多消费者执行

    1.首先介绍下那个时候使用RingBuffer,那个时候使用disruptor ringBuffer比较适合场景比较简单的业务,disruptor比较适合场景较为复杂的业务,很多复杂的结果必须使用di ...

  3. 朱晔的互联网架构实践心得S1E2:屡试不爽的架构三马车

    朱晔的互联网架构实践心得S1E2:屡试不爽的架构三马车 [下载本文PDF进行阅读] 这里所说的三架马车是指微服务.消息队列和定时任务.如下图所示,这里是一个三驾马车共同驱动的一个立体的互联网项目的架构 ...

  4. iOS容易造成循环引用的三种场景

    iOS容易造成循环引用的三种场景  ARC已经出来很久了,自动释放内存的确很方便,但是并非绝对安全绝对不会产生内存泄露.导致iOS对象无法按预期释放的一个无形杀手是--循环引用.循环引用可以简单理解为 ...

  5. 大型网站技术架构(四)--核心架构要素 开启mac上印象笔记的代码块 大型网站技术架构(三)--架构模式 JDK8 stream toMap() java.lang.IllegalStateException: Duplicate key异常解决(key重复)

    大型网站技术架构(四)--核心架构要素   作者:13GitHub:https://github.com/ZHENFENG13版权声明:本文为原创文章,未经允许不得转载.此篇已收录至<大型网站技 ...

  6. OC与Swift混编,三种场景的实现方式

    多语言并存时期,混编成为一种必须的方式 ,在多场影中实现OC和Swift语言的并存原来是如此简单 第一种场景,App中实现混编 创建桥接文件*.h 新建一个桥接文件,New File 选择 Heade ...

  7. LNMP架构三

    Nginx代理(正向代理) 正向代理:让局域网内的用户 访问外网,外网不能访问局域网, 场景:如果要从国内访问美国的服务器会很慢,这时候就可以找个香港服务器做代理,香港访问美国是很快的. 代理服务器作 ...

  8. iOS 应用架构 (三)

    iOS 客户端应用架构看似简单,但实际上要考虑的事情不少.本文作者将以系列文章的形式来回答 iOS 应用架构中的种种问题,本文是其中的第二篇,主要讲 View 层的组织和调用方案.下篇主要讨论做 Vi ...

  9. disruptor架构一

    Disruptor是一个高性能的异步处理框架,或者可以认为是最快的消息框架(轻量的JMS),也可以认为是一个观察者模式的实现,或者事件监听模式的实现. 在使用之前,首先说明disruptor主要功能加 ...

随机推荐

  1. & 异步使用场景

    异步的使用场景: 1.不涉及共享资源,或对共享资源只读,即非互斥操作 2.没有时序上的严格关系 3.不需要原子操作,或可以通过其他方式控制原子性 4.常用于IO操作等耗时操作,因为比较影响客户体验和使 ...

  2. uwsgi+nginx 502 bad get away 错误

    用uwsgi和nginx部署网站时有时候访问网站会出现502错误 配置,启动文件等完全没有问题. 目前解决方法是重启uwsgi就可以了(虽然说502错误应该有很多产生原因啦) 所用命令: $ ps - ...

  3. itext7史上最全实战总结

    1. itext7史上最全实战总结 1.1. 前言 最近有个需求需要我用Java手动写一份PDF报告,经过考察几种pdf开源代码,最终选取了itext7,此版本为7.1.11,由于发现网上关于该工具的 ...

  4. jQuery-DOM增删查改

    1.绑定事件 $().事件名(function(){功能}) 事件名:鼠标事件 键盘事件 表单事件 事件委托:$().on('事件名',#####'target',function(){功能}) 额外 ...

  5. PowerPC-object与elf中的符号引用

    https://mp.weixin.qq.com/s/6snzjEpDT4uQuCI2Nx9VcQ   一. 符号引用 编译会先把每个源代码文件编译成object目标文件,然后把所有目标文件链接到一起 ...

  6. 【HIVE】(1)建表、导入数据、外部表、导出数据

    导入数据 1). 本地 load data local inpath "/root/example/hive/data/dept.txt" into table dept; 2). ...

  7. Java实现 LeetCode 765 情侣牵手(并查集 || 暴力)

    765. 情侣牵手 N 对情侣坐在连续排列的 2N 个座位上,想要牵到对方的手. 计算最少交换座位的次数,以便每对情侣可以并肩坐在一起. 一次交换可选择任意两人,让他们站起来交换座位. 人和座位用 0 ...

  8. Java实现 蓝桥杯VIP 算法训练 整除问题

    问题描述 编写一个程序,输入三个正整数min.max和factor,然后对于min到max之间的每一个整数(包括min和max),如果它能被factor整除,就把它打印出来. 输入格式:输入只有一行, ...

  9. Java实现 洛谷 P1426 小鱼会有危险吗

    import java.util.LinkedList; import java.util.Scanner; public class Main { private static Scanner ci ...

  10. Python:求时间差(天时分秒格式)

    传入一个时间戳,以天时分秒格式打印出时间差 输入一个10位的时间戳,求出时间差 def time_diff(timestamp): onlineTime = datetime.datetime.fro ...