Disruptor

Disruptor是一个高性能的并发框架,采用无锁和环形缓冲设计,避免伪共享问题,提供高效的消息传递。本文从设计思想、快速入门、串行和并行消费、多生产者和消费者以及源码解析等方面详细介绍Disruptor,包括其初始化、生产者、消费者、RingBuffer和等待策略。
摘要由CSDN通过智能技术生成

Disruptor是一个开源的并发框架,提供了类似于Java中有界队列的功能,主要用于生产消费者场景。与Java原生并发队列不同的是,Disruptor高度优化,在单机上可以轻松跑到千万级别的tps与ns级别的延时

Disruptor的设计思想

  • 无锁:加锁会带来线程的切换,这个是非常耗时的,Disruptor使用了CAS和自旋,提高了性能。同样也使用了序号栅栏和序号配合使用避免了锁和CAS操作。
  • 消除伪共享:现代处理器的缓存用法对于成功的高性能操作至关重要。我们的操作系统用64字节的缓存行进行缓存操作。如果有两个变量在相同的缓存行中,且这两个变量是被不同线程写入,这是就会存在写入争用问题,导致缓存行失效。Disruptor用在Long变量的左右增加其他7个填充Long变量,让变量单独存在一个缓存行中,消除了伪共享。
  • 环形缓冲:Disruptor中使用了环形结构,无需浪费大量的空间存储,可以循环利用。底层使用数组结构,而不是使用链表,性能要更好,每个元素都是在在启动时预分配的。所有的元素在Disruptor实例生存周期中都将重用并一直存在。元素在消费者消费完成之后,生产者会对当前未知的元素进行重用。这样避免了垃圾的产生。

Disruptor Quick Start

我们先写一个hello world 程序。要实现Disruptor需要四步:

  • 建立一个工厂Event类,用于创建Event类实例对象。
  • 需要有一个监听事件类,用于处理数据(Event类)。
  • 实例化Disruptor实例,配置一系列参数,编写Disruptor核心组件。
  • 编写生产者组件,向Disruptor容器中去投递数据。

首先我们创建Event类。

public class OrderEvent {
   
    private long value;

    public long getValue() {
   
        return value;
    }

    public void setValue(long value) {
   
        this.value = value;
    }
}

创建工厂类,返回一个未赋值的OrderEvent实例。

public class OrderEventFactory implements EventFactory<OrderEvent> {
   
    @Override
    public OrderEvent newInstance() {
   
        return new OrderEvent();
    }
}

编写一个消费者,这里需要实现一个接口。

public class OrderEventHandler implements EventHandler<OrderEvent> {
   
    @Override
    public void onEvent(OrderEvent orderEvent, long l, boolean b) throws Exception {
   
        System.out.println("消费者" + orderEvent.getValue());
    }
}

编写生产者,这里需要接收RingBuffer实例,用来发送消息。

public class OrderEventProducer {
   
    private RingBuffer<OrderEvent> ringBuffer;

    public OrderEventProducer(RingBuffer<OrderEvent> ringBuffer) {
   
        this.ringBuffer = ringBuffer;
    }

    public void sendData(long value) {
   
        //1 在生产者发送消息时,首先需要从我们的ringBuffer里面 获取一个可用的序号
        long sequence = ringBuffer.next();

        try {
   
            //2 根据这个序号,找到具体的"OrderEvent"元素。注意:此时获取的OrderEvent对象是一个没有被赋值的"空对象"
            OrderEvent orderEvent = ringBuffer.get(sequence);
            //3 进行实际的赋值操作
            orderEvent.setValue(value);
        } finally {
   
            //提交发布操作
            ringBuffer.publish(sequence);
        }
    }
}

主方法中根据上面的步骤实现Disruptor简单的生产和消费。

public class Main {
   
    public static void main(String[] args) {
   
        //准备参数工作
        OrderEventFactory orderEventFactory = new OrderEventFactory();
        int ringBufferSize = 1024 * 1024;
        ThreadFactory springThreadFactory = new CustomizableThreadFactory("springThread-pool-");

        /**
         * 1 orderEventFactory: 消息(Event)工厂对象
         * 2 ringBufferSize: 容器的长度
         * 3 threadFactory: 线程池工厂
         * 4 ProducerType: 单生产者或多生产者
         * 5 waitStrategy: 等待策略
         */
        //1. 实例化Disruptor对象
        Disruptor<OrderEvent> disruptor = new Disruptor(orderEventFactory,
                ringBufferSize,
                springThreadFactory,
                ProducerType.SINGLE,
                new BlockingWaitStrategy());

        //2. 添加消费者监听(构建Disruptor与消费者的一个关联关系)
        disruptor.handleEventsWith(new OrderEventHandler());

        //3. 启动disruptor
        disruptor.start();

        //4. 获取实际存储数据的容器:RingBuffer
        RingBuffer<OrderEvent> ringBuffer = disruptor.getRingBuffer();

        //5. 创建生产者
        OrderEventProducer producer = new OrderEventProducer(ringBuffer);
        for(long i=0;i<100;i++) {
   
            producer.sendData(i);
        }

        //6. 关闭资源
        disruptor.shutdown();
    }
}

启动之后打印消费日志。

消费者0
消费者1
消费者2
...
消费者98
消费者99

Disruptor 串行消费和并行消费

首先我们创建Event类,模拟交易信息。

public class Trade {
   
    private String id;
    private String name;
    private double price;
    private AtomicInteger count = new AtomicInteger(0);

    public String getName() {
   
        return name;
    }

    public String getId() {
   
        return id;
    }

    public AtomicInteger getCount() {
   
        return count;
    }

    public double getPrice() {
   
        return price;
    }

    public void setId(String id) {
   
        this.id = id;
    }

    public void setName(String name) {
   
        this.name = name;
    }

    public void setCount(AtomicInteger count) {
   
        this.count = count;
    }

    public void setPrice(double price) {
   
        this.price = price;
    }
}

交易信息生产者。TradePubshlisher中使用Disruptor进行生产event,通过循环设置一次发送的event数量,需要传入的对象要实现EventTranslator接口。

public class TradePubshlisher implements Runnable {
   
    private CountDownLatch latch;
    private Disruptor<Trade> disruptor;

    private static int PUBLISH_COUNT = 10;

    public TradePubshlisher(CountDownLatch latch, Disruptor<Trade> disruptor) {
   
        this.latch = latch;
        this.disruptor = disruptor;
    }

    @Override
    public void run() {
   
        //新的提交任务方式
        for(int i=0;i<PUBLISH_COUNT;i++) {
   
            disruptor.publishEvent(new TradeEventTranslator());
        }
        latch.countDown();
    }
}

class TradeEventTranslator implements EventTranslator<Trade> {
   
    private Random random = new Random();

    @Override
    public void translateTo(Trade trade, long l) {
   
        this.generateTrade(trade);
    }

    private void generateTrade(Trade event) {
   
        event.setPrice(random.nextDouble() * 9999);
    }
}

创建5个消费者。这里可以通过两种方式实现,实现EventHandler接口或实现WorkHandler。

public class Handler1 implements EventHandler<Trade>, WorkHandler<Trade> {
   
    @Override
    public void onEvent(Trade trade, long l, boolean b) throws Exception {
   
        this.onEvent(trade);
    }

    @Override
    public void onEvent(Trade trade) throws Exception {
   
        System.err.println("handler 1 : SET NAME");
        trade.setName("H1");
        Thread.sleep(1000);
    }
}

public class Handler2 implements EventHandler<Trade> {
   
    @Override
    public void onEvent(Trade trade, long l, boolean b) throws Exception {
   
        System.err.println("handler 2 : SET ID");
        trade.setId(UUID.randomUUID().toString());
        Thread.sleep(2000);
    }
}

public class  Handler3 implements EventHandler<Trade> {
   

    @Override
    public void onEvent(Trade trade, long l, boolean b) throws Exception {
   
        System.err.println("handler 3 : NAME: " + trade.getName() + ", ID: " + trade.getId() + " INSTANCE" +
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值