Disruptor的多生产者和多消费者模式实现
啥也不说了,上代码
1.maven依赖
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>3.3.4</version>
</dependency>
2.实体类
public class Order {
private String id;//ID
private String name;
private double price;
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;
}
}
3.生产者
import com.lmax.disruptor.RingBuffer;
public class Producer {
private final RingBuffer<Order> ringBuffer;
public Producer(RingBuffer<Order> ringBuffer){
this.ringBuffer = ringBuffer;
}
/**
* onData用来发布事件,每调用一次就发布一次事件
* 它的参数会通过事件传递给消费者
*/
public void onData(String data){
//可以把ringbuffer看做一个事件队列,那么next就是得到下面一个事件槽
long sequence = ringBuffer.next();
try{
//用上面的索引取出一个空的事件用于填充(获取该序号对应的事件对象)
Order order = ringBuffer.get(sequence);
//获取要通过事件传递的业务数据
order.setId(data);
}catch (Exception e){
}finally {
//发布事件
//注意,最后的ringbuffer.publish方法必须包含在finally中以确保必须得到调用;
ringBuffer.publish(sequence);
}
}
}
4.消费者
import java.util.concurrent.atomic.AtomicInteger;
public class Consumer implements WorkHandler<Order> {
private String consumerId;
private static AtomicInteger count = new AtomicInteger(0);
public Consumer(String consumerId){
this.consumerId = consumerId;
}
@Override
public void onEvent(Order order) throws Exception {
System.out.println("当前消费者:"+this.consumerId+",消费信息:"+order);
count.incrementAndGet();
}
public int getCount(){
return count.get();
}
}
5.业务测试类
import com.lmax.disruptor.*;
import com.lmax.disruptor.dsl.ProducerType;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) throws Exception{
/**
* ProducerType.MULTI,多个生产者
* EventFactory,它的职责是产生数据填充RingBuffer的区块
* RingBuffer的大小,它必须是2的倍数,目的是为了提高运算效率(涉及到求模和&运算)
* RingBuffer的生产者在没有可用区块时(也可能是消费者(或者访问是事件处理器)太慢了)的等待策略
*/
RingBuffer<Order> ringBuffer =//线路单一时用ringbuffer
RingBuffer.create(ProducerType.MULTI,
new EventFactory<Order>() {
@Override
public Order newInstance() {
return new Order();
}
},1024*1024,new YieldingWaitStrategy());
//创建SequenceBarrier,平衡生产和消费数据的速度
SequenceBarrier sequenceBarrier = ringBuffer.newBarrier();
Consumer[] consumers = new Consumer[3];
for (int i=0;i<3;i++){
consumers[i] = new Consumer("c"+i);
}
//1.第一个参数:数据来源
//2.第二个参数:做生产者和消费者的平衡
//3.第三个参数:抛异常时的处理机制
//4.第四个参数:消费者
WorkerPool<Order> workerPool =
new WorkerPool<Order>(ringBuffer,sequenceBarrier,new IntEventExceptionHandler(),consumers);
//这一步的目的是把消费者的位置信息引用注入到生产者,如果只有一个消息费者的情况可以省略
ringBuffer.addGatingSequences(workerPool.getWorkerSequences());//三个消费者,每个消费者的消费进度,消费下标扔给生产者(三个消费者的进度直接设置到ringbuffer中,生产就可以获取了)
workerPool.start(Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()));//根据机器性能,获得当前机器的线程数,创建固定数量的线程池
final CountDownLatch latch = new CountDownLatch(1);
//生产8个数据
for (int i=0;i<100;i++){
final Producer p = new Producer(ringBuffer);
new Thread(new Runnable() {
@Override
public void run() {
try {
latch.await();
}catch (InterruptedException e){
e.printStackTrace();
}
for(int j=0;j<100;j++){
p.onData(UUID.randomUUID().toString());
}
}
}).start();
}
Thread.sleep(2000);
System.out.println("----------开始生产--------------");
latch.countDown();//同时进行生产
Thread.sleep(5000);
System.out.println("总数:"+consumers[0].getCount());
}
static class IntEventExceptionHandler implements ExceptionHandler{
@Override
public void handleEventException(Throwable throwable, long l, Object o) {
}
@Override
public void handleOnStartException(Throwable throwable) {
}
@Override
public void handleOnShutdownException(Throwable throwable) {
}
}
}
6.执行结果