Disruptor的多生产者和多消费者模式实现

Disruptor的多生产者和多消费者模式实现

啥也不说了,上代码

1.maven依赖
<!-- https://mvnrepository.com/artifact/com.lmax/disruptor -->
        <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.执行结果

在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值