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 ...
随机推荐
- Linux安装Oracle 11g Grid Infrastructure 出现OUI-10182错误解决办法
已确保安装的ORACLE_BASE目录是属于grid:oinstall 但安装时总是报:OUI-10182 The effective user ID does not match the own ...
- UIActivityIndicatorView 的使用
// // UIActivityIndicator.m // ToolBar // // Created by lanouhn on 15/1/3. // Copyright (c) 2015 ...
- 《ARM Cortex-M3权威指南》笔记(1)
http://blog.csdn.net/roverx/article/details/6624859 第1章 介绍 一.ARM Cortex‐M3处理器初探 CM3处理器内核是单片机的中央处理单元( ...
- 20155326 《Java程序设计》第8周学习总结
20155326 <Java程序设计>第8周学习总结 教材学习内容总结 NIO (1)NIO使用频道来衔接数据节点,在处理数据时,NIO可以让你设定缓冲区容量,在缓冲区中对感兴趣的数据区块 ...
- 初始kafka
kafka 简介 Kafka是Linkedin于2010年12月份开源的消息系统 一种分布式的.基于发布/订阅的消息系统 ,另外提供数据分布式缓存功能 特点 消息持久化:通过O(1)的磁盘数据结构提供 ...
- Android之TextView灵活使用
Android之TextView灵活使用 在项目中有无遇到过这样一种程况,例如文字"王明今年10岁了", 但是数字10是从网络返回的数据, 而你又想把这个文字写在xml中, 过往我 ...
- [转载]DevOps发展的四个重要阶段
DevOps是敏捷开发的延续,它将敏捷的精神延伸至IT运营(IT Operation)阶段.敏捷开发的主要目的是响应变化,快速交付价值.以2001年的敏捷宣言发布这个里程碑为起点,开始几年内企业主要在 ...
- C#调用haskell遭遇Attempted to read or write protected memory
1. Haskell的代码如下: 上面的代码中readMarkdown与writeHtmlString是pandoc中的函数,newString的作用是将String转换为IO CString. 2. ...
- C#常用修饰符
访问修饰符 访问修饰符是一些关键字,用于指定声明的成员或类型的可访问性,C#有4个访问修饰符:public.private.protected.internal,使用这些访问修饰符可以指定以下5个访问 ...
- NPOI自适应列宽
当本地没有安装Excel,但是又想导出Excel,采用Office插件是行不通的,NPOI是导出Excel的一个开源的插件.在导出Excel后,为了方便阅读,可以才采用自适应列宽的方式使得单元格的宽度 ...