在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. 是时候扔掉cmder, 换上Windows Terminal

    作为一个Windows的长期用户,一直没有给款好用的终端,知道遇到了 cmder,它拯救一个习惯用Windows敲shell命令的人. 不用跟我安利macOS真香!公司上班一直用macOS,一方面确实 ...

  2. 相邻元素margin的自动合并与float的坑

    css中相邻元素的margin其实是会自动合并的,且取较大值. <!DOCTYPE html> <html lang="en"> <head> ...

  3. 快速复习C语言 - 1变量与运算符

    变量与运算符 本篇以读者知道 int.char.float.double 等数据类型为前提条件. float 类型注意事项 float 类型数没有办法跟一个数真正比较是否相等,可以定义借助绝对值在一定 ...

  4. 【Hadoop】hdfs的秘密,namenode,datanode,yarn,安全模式,fsimage,edits...

    1.bin/hdfs namenode -format ** 注意事项 1.在配置好了配置文件之后,首次启动之前,做初始化操作 2.在后续启动的时候,不需要再初始化 3.初始化的一些影响 一.初始化操 ...

  5. Redis高可用-主从,哨兵,集群

    主从复制 Master-Slave主从概念 同时运行多个redis服务端,其中一个作为主(master),其他的一个或多个作为从(slave),主从之间通过网络进行通讯,slave通过复制master ...

  6. Spring (一 ) 概述与介绍

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 目录 1.Spring概述 2.Spring的模块介绍 Spring框架分为四大模块: 3.Eclips ...

  7. Java实现 蓝桥杯VIP 算法训练 平方计算

    问题描述 输入正整数a, m,输出a2%m,其中表示乘方,即a^2表示a的平方,%表示取余. 输入格式 输入包含两个整数a, m,a不超过10000. 输出格式 输出一个整数,即a^2%m的值. 样例 ...

  8. Java实现复数运算

    1 问题描述 编程实现两个复数的运算.设有两个复数 和 ,则他们的运算公式为: 要求:(1)定义一个结构体类型来描述复数. (2)复数之间的加法.减法.乘法和除法分别用不用的函数来实现. (3)必须使 ...

  9. java实现罗马数字转十进制

    古罗马帝国开创了辉煌的人类文明,但他们的数字表示法的确有些繁琐,尤其在表示大数的时候,现在看起来简直不能忍受,所以在现代很少使用了.之所以这样,不是因为发明表示法的人的智力的问题,而是因为一个宗教的原 ...

  10. Java实现填符号凑算式

    匪警请拨110,即使手机欠费也可拨通! 为了保障社会秩序,保护人民群众生命财产安全,警察叔叔需要与罪犯斗智斗勇,因而需要经常性地进行体力训练和智力训练! 某批警察叔叔正在进行智力训练: 1 2 3 4 ...