Disruptor多个消费者不重复处理生产者发送过来的消息
1、定义事件
事件(Event)就是通过 Disruptor 进行交换的数据类型。
package com.ljq.disruptor; import java.io.Serializable; /**
* 定义事件数据,本质是个普通JavaBean
*
* @author jqlin
*/
@SuppressWarnings("serial")
public class LongEvent implements Serializable {
private long value; public LongEvent() {
super();
} public LongEvent(long value) {
super();
this.value = value;
} public long getValue() {
return value;
} public void setValue(long value) {
this.value = value;
} @Override
public String toString() {
return "LongEvent [value=" + value + "]";
} }
2、LongEvent事件生产者
package com.ljq.disruptor; import com.lmax.disruptor.RingBuffer; /**
* LongEvent事件生产者,生产LongEvent事件
*
* @author jqlin
*/
public class LongEventProducer {
private final RingBuffer<LongEvent> ringBuffer; public LongEventProducer(RingBuffer<LongEvent> ringBuffer) {
this.ringBuffer = ringBuffer;
} public void produceData(long value) {
long sequence = ringBuffer.next(); // 获得下一个Event槽的下标
try {
// 给Event填充数据
LongEvent event = ringBuffer.get(sequence);
event.setValue(value); } finally {
// 发布Event,激活观察者去消费, 将sequence传递给该消费者
// 注意,最后的 ringBuffer.publish() 方法必须包含在 finally 中以确保必须得到调用;如果某个请求的 sequence 未被提交,将会堵塞后续的发布操作或者其它的 producer。
ringBuffer.publish(sequence);
}
}
}
3、LongEvent事件消息者
package com.ljq.disruptor; import com.lmax.disruptor.WorkHandler; /**
* LongEvent事件消息者,消息LongEvent事件
*
* @author Administrator
*
*/
public class LongEventConsumer implements WorkHandler<LongEvent> { @Override
public void onEvent(LongEvent event) throws Exception {
System.out.println("consumer:" + Thread.currentThread().getName() + " Event: value=" + event.getValue() );
} }
4、ProducerConsumerMain
消费者-生产者启动类,其依靠构造Disruptor对象,调用start()方法完成启动线程。
package com.ljq.disruptor; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import com.lmax.disruptor.EventFactory;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.SequenceBarrier;
import com.lmax.disruptor.WorkerPool;
import com.lmax.disruptor.YieldingWaitStrategy;
import com.lmax.disruptor.dsl.ProducerType; /**
* Disruptor多个消费者不重复处理生产者发送过来的消息
*
* @author Administrator
*
*/
public class ProducerConsumerMain {
public static void main(String[] args) throws InterruptedException {
Long time = System.currentTimeMillis(); // 指定 ring buffer字节大小,必需为2的N次方(能将求模运算转为位运算提高效率 ),否则影响性能
int bufferSize = 1024 * 1024;;
//固定线程数
int nThreads = 10; ExecutorService executor = Executors.newFixedThreadPool(nThreads); EventFactory<LongEvent> factory = new EventFactory<LongEvent>() {
@Override
public LongEvent newInstance() {
return new LongEvent();
}
}; // 创建ringBuffer
RingBuffer<LongEvent> ringBuffer = RingBuffer.create(ProducerType.MULTI, factory, bufferSize, new YieldingWaitStrategy());
SequenceBarrier barriers = ringBuffer.newBarrier();
// 创建10个消费者来处理同一个生产者发送过来的消息(这10个消费者不重复消费消息)
LongEventConsumer[] consumers = new LongEventConsumer[50];
for (int i = 0; i < consumers.length; i++) {
consumers[i] = new LongEventConsumer();
}
WorkerPool<LongEvent> workerPool = new WorkerPool<LongEvent>(ringBuffer, barriers,
new EventExceptionHandler(), consumers);
ringBuffer.addGatingSequences(workerPool.getWorkerSequences());
workerPool.start(executor); LongEventProducer producer = new LongEventProducer(ringBuffer);
for (int i = 0; i < 20000; i++) {
producer.produceData(i);
} Thread.sleep(1000); //等上1秒,等消费都处理完成
workerPool.halt(); //通知事件(或者说消息)处理器 可以结束了(并不是马上结束!!!)
executor.shutdown();
System.out.println("总共耗时(单位毫秒) :" + (System.currentTimeMillis() - time));
}
}
5、EventExceptionHandler
package com.ljq.disruptor;
import com.lmax.disruptor.ExceptionHandler;
public class EventExceptionHandler implements ExceptionHandler {
@Override
public void handleEventException(Throwable ex, long sequence, Object event) {
System.out.println("handleEventException:" + ex);
}
@Override
public void handleOnShutdownException(Throwable ex) {
System.out.println("handleEventException:" + ex);
}
@Override
public void handleOnStartException(Throwable ex) {
System.out.println("handleOnStartException:" + ex);
}
}
Disruptor多个消费者不重复处理生产者发送过来的消息的更多相关文章
- kafka 消费组功能验证以及消费者数据重复数据丢失问题说明 3
原创声明:作者:Arnold.zhao 博客园地址:https://www.cnblogs.com/zh94 背景 上一篇文章记录了kafka的副本机制和容错功能的说明,本篇则主要在上一篇文章的基础上 ...
- rabbitmq消息队列,消息发送失败,消息持久化,消费者处理失败相关
转:https://blog.csdn.net/u014373554/article/details/92686063 项目是使用springboot项目开发的,前是代码实现,后面有分析发送消息失败. ...
- Kafka生产者发送消息的三种方式
Kafka是一种分布式的基于发布/订阅的消息系统,它的高吞吐量.灵活的offset是其它消息系统所没有的. Kafka发送消息主要有三种方式: 1.发送并忘记 2.同步发送 3.异步发送+回调函数 下 ...
- 深入研究RocketMQ生产者发送消息的底层原理
前言 hello,小伙伴们,王子又来和大家研究RocketMQ的原理了,之前的文章RocketMQ生产部署架构如何设计中,我们已经简单的聊过了生产者是如何发送消息给Broker的. 我们简单回顾一下这 ...
- java生产者/消费者模式实现——一生产者一消费者(操作值)
胶多不粘话多不甜,直接上代码: 生产者类: /** * Created by 51304 on 2016/2/28. */ public class P { private String lock; ...
- 设有三个进程A、B、C,其中A与B构成一对生产者与消费者(A为生产者,B为消费者),共享一个由n个缓冲块组成的缓冲池;B与C也构成一对生产者与消费者(此时B为生产者,C为消费者)共享另一个由m个缓冲块组成的缓冲池。用P、V操作描述它们之间的同步关系。
生产者消费者问题 设信号量mutex1, mutex2, full1, full2, empty1, empty2分别表示1和2号缓冲区的访问互斥, 是否满, 是否空 semaphore mutex1 ...
- kafka 生产者发送消息
KafkaProducer 创建一个 KafkaThread 来运行 Sender.run 方法. 1. 发送消息的入口在 KafkaProducer#doSend 中,但其实是把消息加入到 batc ...
- RocketMQ3.2.2生产者发送消息自动创建Topic队列数无法超过4个
问题现象 RocketMQ3.2.2版本,测试时尝试发送消息时自动创建Topic,设置了队列数量为8: producer.setDefaultTopicQueueNums(8); 同时设置broker ...
- [SoapUI] 设置最大等待时间,不断重复的去发送一个request,每次从response中获取一个status,直到这个status从一种状态变成另外一种状态
import com.eviware.soapui.support.GroovyUtils def groovyUtils = new GroovyUtils( context ) def holde ...
随机推荐
- C++之const限定符(顶层const,底层const)
作者:tongqingliu 转载请注明出处:http://www.cnblogs.com/liutongqing/p/7050815.html C++之const限定符(顶层const,底层cons ...
- php实现网站四则运算。
1.设计思路: 在index.php中建立两个表单,有两个提交,一个跳转到fourArithmeticOperation.php,这里保存用户输入的参数到config.txt中,留给main函数调出. ...
- noip第7课资料
- Navicat连接mysql8.0.1版本出现1251--Client does not support authentication protocol requested by server的解决
转载自:https://blog.csdn.net/XDMFC/article/details/80263215 好不容易安装好mysql,但又出现了mysql客户端版本太低的问题.根据参考的这篇博客 ...
- lis nlogn算法
当前所在位的最长上升子序列只和前面一个字符有关 #include <iostream> #include <algorithm> using namespace std; ]; ...
- codeforces 434D
题意:有n<=50个点,每个点有xi有[li, ri]种取值,-100 <= li <= ri <= 100,并且给定m<=100条边,每条边为u,v,d表示xu< ...
- LigerUi中为Grid表加上序号,并调整适当宽度!(实例)
LigerUi中为Grid表加上序号,并调整适当宽度!(实例) dataAction: 'server', pageSize: 20, toolbar: {}, url: 'ndl ...
- 机器学习实战-ch3-决策树
决策树是一种新算法: 优点:计算复杂度不高,输出结果易于理解,对中间值的缺失不敏感,可以处理不相关特征数据.缺点:可能会产生过度匹配问题. 决策树算法可用于数据类型:数值型和标称型. 决策树的核心在于 ...
- MySQL--Ansible推送密钥实现免密码登录
从别人网站抄过来,保留自用 场景: 对于需要管理的很多linux服务器,每次登录都输入密码比较痛苦,配置一个跳板机,将本地公钥推送带各访问节点上实现SSH登录 登录账号:admin 本地秘钥路径:/h ...
- Docker Compose模板文件介绍
模板文件是使用 Compose 的核心,涉及到的指令关键字也比较多,这里面大部分指令跟 docker run 相关参数的含义都是类似的.默认的模板文件名称为 docker-compose.yml ,格 ...