在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. Centos8 删除了yum.repos.d 下面的文件

    原文: https://www.cnblogs.com/junjind/p/9016107.html centos-release-8.1-1.1911.0.9.el8.x86_64 找到 https ...

  2. jchdl - RTL Block

    https://mp.weixin.qq.com/s/pR6b6i98P9dRU8bhZkKaww   观察Verilog代码可以发现,对逻辑的描述中都是assign和always代码块.这正对应了硬 ...

  3. 【积累】如何优雅关闭SpringBoot Web服务进程

    1.使用ps ef查出进程对应的pid. 2.使用kill -15 pid结束进程. 为什么不使用kill -9 pid,个人理解kill -15 pid更优雅,能在结束进程前执行spring容器清理 ...

  4. 【HBase】表的version

    建表.添加数据 Examples: hbase> create 'ns1:t1', 'f1', SPLITS => ['10', '20', '30', '40'] hbase> c ...

  5. Mybatis 的动态SQL,批量增删查改

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 批量增删改的接口: public interface BookService { //批量增加 int ...

  6. Java实现 蓝桥杯VIP 基础练习 Sine之舞

    问题描述 最近FJ为他的奶牛们开设了数学分析课,FJ知道若要学好这门课,必须有一个好的三角函数基本功.所以他准备和奶牛们做一个"Sine之舞"的游戏,寓教于乐,提高奶牛们的计算能力 ...

  7. Android Button的四种点击事件

    bta1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.m ...

  8. java实现坐标

    * 已知平面上若干个点的坐标. 需要求出在所有的组合中,4 个点间平均距离的最小值(四舍五入,保留 2 位小数). 比如有 4 个点:a,b,c,d,则平均距离是指:ab, ac, ad, bc, b ...

  9. java实现第七届蓝桥杯有奖竞猜

    有奖竞猜 题目描述 小明很喜欢猜谜语. 最近,他被邀请参加了X星球的猜谜活动. 每位选手开始的时候都被发给777个电子币. 规则是:猜对了,手里的电子币数目翻倍, 猜错了,扣除555个电子币, 扣完为 ...

  10. 全面概述Gitee和GitHub生成/添加SSH公钥

    前言 现如今将代码开源已经成为软件开发行业的一种趋势,而现在比较有名的代码托管平台有GItHub.Gitee.Gitlab等相关平台.而我们在使用代码托管平台最为常见的就是如何将自己本地的代码推送到远 ...