单一的生产者,消费者有多个,使用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. share pool 管理机制

    Library cache是Shared pool的一部分,它几乎是Oracle内存结构中最复杂的一部分,主要存放shared curosr(SQL)和PLSQL对象(function,procedu ...

  2. jvm的内存分配

    java内存分配 A:栈 存储局部变量 B:堆 存储所有new出来的 C:方法区(方法区的内存中) 类加载时 方法信息保存在一块称为方法区的内存中, 并不随你创建对象而随对象保存于堆中; D:本地方法 ...

  3. 20169207《Linux内核原理与分析》第九周作业

    第九周的实验依旧和往常的一样,主要包括两部分.一是1.阅读学习教材「Linux内核设计与实现 (Linux Kernel Development)」第教材第13,14章.二是学习MOOC「Linux内 ...

  4. Phalanx (hdu 2859)

    http://acm.hdu.edu.cn/showproblem.php?pid=2859     Time Limit: 10000/5000 MS (Java/Others)    Memory ...

  5. Alpha冲刺 - (3/10)

    Part.1 开篇 队名:彳艮彳亍团队 组长博客:戳我进入 作业博客:班级博客本次作业的链接 Part.2 成员汇报 组员1(组长)柯奇豪 过去两天完成了哪些任务 ssm框架的使用并实现简单的数据处理 ...

  6. Windows Phone 8.1不完全体验报告

    在Build 2014中,微软倾心打造的Windows Phone 8.1终于粉墨登场,会场掌声不断.在大会结束后一周,经过漫长的等待,终于等到了开发者预览的推送,迫不及待地体验这一跨时代的移动系统. ...

  7. Amoeba常见问题

    1.1.1 JAVA_HOME不认 jdk安装后测试无问题java –version,但启动amoeba就是报错JAVA_HOME找不到.就修改/amoeba/bin/amoeba文件,在文件最开头直 ...

  8. cxGrid实现取消过滤和排序后定位到首行(单选和多选)

    cxGrid实现取消过滤和排序后定位到首行(单选和多选) 原创 2013年10月06日 18:42:24 2107 DataContoller中的函数FocusedRecordIndex没有反应,Fo ...

  9. Android-Java-synchronized同步代码块的使用场景

    synchronized同步代码块的使用场景 (满足以下两种条件,就要考虑使用synchronize同步代码块了) 1.被synchronized同步代码块{同步的代码},是被多次异步调用,什么叫多次 ...

  10. 转(C# 类似右键菜单弹出窗体)

    文章来自 https://www.cnblogs.com/ahdung/p/FloatLayerBase.html 每天进步一点点 新建类  FloatLayerBase 继承Form, 自己有点小改 ...