单一的生产者,消费者有多个,使用WorkerPool来管理多个消费者;

RingBuffer在生产Sequencer中记录一个cursor,追踪生产者生产到的最新位置,通过WorkSequence和sequence记录整个workpool消费的位置和每个WorkProcessor消费到位置,来协调生产和消费程序

1、定义事件

package com.ljq.disruptor;

import java.io.Serializable;

/**
* 交易事件数据
*
* @author Administrator
*
*/
@SuppressWarnings("serial")
public class TradeEvent implements Serializable {
private String id; // 订单ID
private String name;
private double price; // 金额 public TradeEvent() {
} public TradeEvent(String id) {
super();
this.id = id;
} 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;
} @Override
public String toString() {
return "Trade [id=" + id + ", name=" + name + ", price=" + price + "]";
} }

2、TradeEvent事件消费者

package com.ljq.disruptor;

import com.lmax.disruptor.EventHandler;
import com.lmax.disruptor.WorkHandler; public class TradeEventHandler implements EventHandler<TradeEvent>, WorkHandler<TradeEvent> {
@Override
public void onEvent(TradeEvent event, long sequence, boolean endOfBatch) throws Exception {
this.onEvent(event);
} /**
* WorkProcessor多线程排队领event然后再执行,不同线程执行不同的event。但是多了个排队领event的过程,这个是为了减少对生产者队列查询的压力
*/
@Override
public void onEvent(TradeEvent event) throws Exception {
// 具体的消费逻辑
System.out.println("consumer:" + Thread.currentThread().getName() + " Event: value=" + event);
}
}

3、EventProcessor消费者-生产者启动类

package com.ljq.disruptor;

import java.util.UUID;
import java.util.concurrent.Callable;
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.RingBuffer;
import com.lmax.disruptor.SequenceBarrier;
import com.lmax.disruptor.YieldingWaitStrategy; public class EventProcessorMain {
public static void main(String[] args) throws Exception {
long beginTime = System.currentTimeMillis(); // 指定 ring buffer字节大小,必需为2的N次方(能将求模运算转为位运算提高效率 ),否则影响性能
int bufferSize = 1024;
//固定线程数
int nThreads = 4; EventFactory<TradeEvent> eventFactory = new EventFactory<TradeEvent>() {
@Override
public TradeEvent newInstance() {
return new TradeEvent(UUID.randomUUID().toString());
}
}; //RingBuffer. createSingleProducer创建一个单生产者的RingBuffer
//第一个参数叫EventFactory,从名字上理解就是“事件工厂”,其实它的职责就是产生数据填充RingBuffer的区块。
//第二个参数是RingBuffer的大小,它必须是2的整数倍,目的是为了将求模运算转为&运算提高效率
//第三个参数是RingBuffer的生产在没有可用区块的时候(可能是消费者太慢了)的等待策略
final RingBuffer<TradeEvent> ringBuffer = RingBuffer.createSingleProducer(eventFactory, bufferSize, new YieldingWaitStrategy()); //SequenceBarrier, 协调消费者与生产者, 消费者链的先后顺序. 阻塞后面的消费者(没有Event可消费时)
SequenceBarrier sequenceBarrier = ringBuffer.newBarrier(); //创建消费者事件处理器, 多线程并发执行,不同线程执行不同的event
BatchEventProcessor<TradeEvent> transProcessor = new BatchEventProcessor<TradeEvent>(ringBuffer, sequenceBarrier, new TradeEventHandler());
//把消费者的消费进度情况注册给RingBuffer结构(生产者),如果只有一个消费者的情况可以省略
ringBuffer.addGatingSequences(transProcessor.getSequence()); //创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程
ExecutorService executors = Executors.newFixedThreadPool(nThreads);
//把消费者提交到线程池,说明EventProcessor实现了callable接口
executors.submit(transProcessor); // 生产者,这里新建线程不是必要的
Future<?> future= executors.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
long seq;
for (int i = 0; i < 100000; i++) {
seq = ringBuffer.next();
ringBuffer.get(seq).setPrice(i);
ringBuffer.publish(seq);
}
return null;
}
});
future.get();//等待生产者结束 Thread.sleep(1000); //等上1秒,等消费都处理完成
transProcessor.halt(); //通知事件(或者说消息)处理器 可以结束了(并不是马上结束!!!)
executors.shutdown(); System.out.println(String.format("总共耗时%s毫秒", (System.currentTimeMillis() - beginTime))); }
}

4、WorkerPool消费者-生产者启动类

package com.ljq.disruptor;

import java.util.UUID;
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.WorkerPool; public class WorkPoolMain {
public static void main(String[] args) throws InterruptedException {
// 指定 ring buffer字节大小,必需为2的N次方(能将求模运算转为位运算提高效率 ),否则影响性能
int bufferSize = 1024;
//固定线程数
int nThreads = 4; //RingBuffer. createSingleProducer创建一个单生产者的RingBuffer
RingBuffer<TradeEvent> ringBuffer = RingBuffer.createSingleProducer(new EventFactory<TradeEvent>() {
public TradeEvent newInstance() {
return new TradeEvent(UUID.randomUUID().toString());
}
}, bufferSize); SequenceBarrier sequenceBarrier = ringBuffer.newBarrier(); WorkerPool<TradeEvent> workerPool = new WorkerPool<TradeEvent>(ringBuffer, sequenceBarrier,
new IgnoreExceptionHandler(), new TradeEventHandler()); //创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程
ExecutorService executors = Executors.newFixedThreadPool(nThreads);
workerPool.start(executors); // 生产10个数据
for (int i = 0; i < 80000; i++) {
long seq = ringBuffer.next();
ringBuffer.get(seq).setPrice(i);
ringBuffer.publish(seq);
} Thread.sleep(1000); //等上1秒,等消费都处理完成
workerPool.halt(); //通知事件(或者说消息)处理器 可以结束了(并不是马上结束!!!)
executors.shutdown();
}
}

EventProcessor与WorkPool用法--可处理多消费者的更多相关文章

  1. Disruptor框架EventProcessor和Workpool的使用

    场景使用: 在HelloWorld的实例中,我们创建Disruptor实例,然后调用getRingBuffer方法去获取RingBuffer,其实在很多时候,我们可以直接使用RingBuffer,以及 ...

  2. Disruptor框架中生产者、消费者的各种复杂依赖场景下的使用总结

    版权声明:原创作品,谢绝转载!否则将追究法律责任. Disruptor是一个优秀的并发框架,可以实现单个或多个生产者生产消息,单个或多个消费者消息,且消费者之间可以存在消费消息的依赖关系.网上其他博客 ...

  3. Disruptor快速入门

    在JDK的多线程与并发库一文中, 提到了BlockingQueue实现了生产者-消费者模型 BlockingQueue是基于锁实现的, 而锁的效率通常较低. 有没有使用CAS机制实现的生产者-消费者? ...

  4. Java编程的逻辑 (61) - 内存映射文件及其应用 - 实现一个简单的消息队列

    本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...

  5. Streams:深入剖析Redis5.0全新数据结构

    Streams:深入剖析Redis5.0全新数据结构   原创: 阿飞的博客   Redis 5.0 全新的数据类型:streams,官方把它定义为:以更抽象的方式建模日志的数据结构.Redis的st ...

  6. Python生产者producer和consumer消费者案例写法,含有多线程,包含队列queue、JoinableQueue队列的用法

    import timeimport random import queuefrom multiprocessing import Process,Queue 案例一:def consumer(q,na ...

  7. 通过消费者和生产者的多线程程序,了解Java的wait()和notify()用法

    仓库类 public class Store { private int size = 0;//当前容量 private final int MAX = 10;//最大容量 //向仓库中增加货物 pu ...

  8. JUC 并发编程--02,生产者和消费者 synchronized的写法 , juc的写法. Condition的用法

    synchronized的写法 class PCdemo{ public static void main(String[] args) { //多个线程操作同一资源 Data data = new ...

  9. 【源码】RingBuffer(二)——消费者

    消费者如何读取数据? 前一篇是生产者的处理,这一篇讲消费者的处理 我们都知道,消费者无非就是不停地从队列中读取数据,处理数据.但是与BlockedQueue不同的是,RingBuffer的消费者不会对 ...

随机推荐

  1. 2.2.2synchronized同步代码块的使用

    当两个并发线程访问同一个对象object中的synchronized(this)同步代码块时,一段时间内只能有一个线程执行,另一个线程必须等待期执行完才能执行. package com.cky.bea ...

  2. python使用数据库的一些操作

    学py感觉还是用linux操作系统比较好,下载安装mysql很简单,linux里面都有自带的,但是要用python去用mysql我们就得安装一下他的模块,因为python里面没有自带他的模块,用yum ...

  3. URAL1099. Work Scheduling(一般图匹配带花树开花算法)

    1099. Work Scheduling Time limit: 0.5 second Memory limit: 64 MB There is certain amount of night gu ...

  4. 基于MATLAB的Sobel边缘检测算法实现

    图像边缘就是图像灰度值突变的地方,也就是图像在该部分的像素值变化速度非常之快,就比如在坐标轴上一条曲线有刚开始的平滑突然来个大转弯,在变化出的导数非常大. Sobel算子主要用作边缘检测,它是一离散型 ...

  5. openresty + lua 3、openresty http 调用

    http 的话,openresty 已经集成,ng 的话,自己引入即可. github 地址:https://github.com/pintsized/lua-resty-http github 里提 ...

  6. 马士兵 spring 视频笔记

    课程内容 1.       面向接口(抽象)编程的概念与好处 2.       IOC/DI的概念与好处 a)       inversion of control b)       dependen ...

  7. SRM477

    250pt: 题意:给定一块蜂巢状的N*M矩阵,每块六边形和周围6个六边形相邻,现在告诉你哪些是陆地,哪些是水,问水陆交界处的长度. 思路:直接模拟 code: #line 7 "Islan ...

  8. Linked List

    链表是线性表的一种.线性表是最基本,最简单也是最常见的一种数据结构.线性表中数据元素之间的关系是一对一的关系,除了第一个和最后一个数据元素外,其他数据元素都是首尾相接的. 线性表有两种存储方式,一种是 ...

  9. Kali Linux渗透测试实战 1.3 渗透测试的一般化流程

    1.3 渗透测试的一般化流程 凡事预则立,不预则废,做任何事情都要有一个预先的计划.渗透测试作为测试学科的一个分支,早已形成了完整的方法论.在正式开始本书的实践教学章节之前,我也想谈一谈使用Kali ...

  10. Rabbit MQ 入门指南

    rabbitMQ是一个在AMQP协议标准基础上完整的,可服用的企业消息系统.他遵循Mozilla Public License开源协议.采用 Erlang 实现的工业级的消息队列(MQ)服务器. Ra ...