Disruptor源码分析

本文介绍了Disruptor框架在Java中的使用,展示了单生产者单消费者和多生产者多消费者两种场景的实现。代码示例详细说明了如何创建Disruptor实例,配置线程池,设置事件处理器,以及使用EventTranslator发送事件。同时,解释了内存屏障和volatile关键字在并发中的作用,确保消费者能获取最新的序列号。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.代码

1.单生产者,单个消费

单个生产,单个消费主函数

import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.YieldingWaitStrategy;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;

import java.nio.ByteBuffer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;


/**
 * 单个生产者,单个消费者
 */
public class SingleDisruptorTest {

    public static void main(String[] args) {
        OrderEventFactor eventFactory = new OrderEventFactor();
        int ringBufferSize = 4;

        //创建线程工厂,为了线程命名
        ThreadFactory tf = new CustomizableThreadFactory("springThread-pool-");
        ExecutorService executorService = Executors.newFixedThreadPool(5, tf);

        Disruptor<OrderEvent> disruptor = new Disruptor(
                eventFactory,
                ringBufferSize,
                executorService,
                ProducerType.SINGLE,
                new YieldingWaitStrategy());

        //消费者监听
        disruptor.handleEventsWith(new OrderEventHandle());
        disruptor.start();

        RingBuffer<OrderEvent> ringBuffer = disruptor.getRingBuffer();
        //初始化生产者
        OrderEventProducer orderEventProducer = new OrderEventProducer(ringBuffer);

        ByteBuffer buffer = ByteBuffer.allocate(8);

        for (long i = 0; i < 5; i++) {
            buffer.putLong(0, i);
            //发送数据
            orderEventProducer.sendData(buffer);
        }
        disruptor.shutdown();
        executorService.shutdown();
    }
}

数据model

import lombok.Data;
@Data
public class OrderEvent {

    private Long value;

    private String name;
}

数据工厂

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

生产者

import com.lmax.disruptor.RingBuffer;

import java.nio.ByteBuffer;

public class OrderEventProducer {

    private RingBuffer<OrderEvent> ringBuffer;

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

    public void sendData(ByteBuffer byteBuffer) {
        //1.在生产者发送消息时,在RingBuff中获取一个可用的序号
        long sequence = ringBuffer.next();
        try {
            //2.根据序号找到对应的event,这个event还没有被赋值
            OrderEvent orderEvent = ringBuffer.get(sequence);
            //3.进行赋值处理
            orderEvent.setValue(byteBuffer.getLong(0));
        } finally {
            //4.进行发布
            ringBuffer.publish(sequence);
        }
    }
}

消费者

import com.lmax.disruptor.EventHandler;

public class OrderEventHandle implements EventHandler<OrderEvent> {
    @Override
    public void onEvent(OrderEvent event, long sequence, boolean endOfBatch) throws Exception {
        System.out.println("线程名"+Thread.currentThread().getName()+"消费者:"+event.getValue());
    }
}

2.多生产者,多消费

在这里插入图片描述

package leetcode.editor.cn.disruptor;

import com.lmax.disruptor.YieldingWaitStrategy;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;


/**
 * 多个生产者,多个消费者
 */
public class MultiDisruptorTest {

    public static void main(String[] args) throws InterruptedException {
        OrderEventFactor eventFactory = new OrderEventFactor();
        int ringBufferSize = 4;

        //创建线程工厂,为了线程命名
        ThreadFactory tf = new CustomizableThreadFactory("springThread-pool-");
        ExecutorService executorService = Executors.newFixedThreadPool(5, tf);

        Disruptor<OrderEvent> disruptor = new Disruptor(
                eventFactory,
                ringBufferSize,
                executorService,
                ProducerType.MULTI,
                new YieldingWaitStrategy());


        //串行操作
        //disruptor.handleEventsWith(new Handle1()).handleEventsWith(new Handle2()).handleEventsWith(new Handle3());
        //并行操作
        //disruptor.handleEventsWith(new Handle1(),new Handle2(),new Handle3());
        //菱形操作,handle1和handle2并行执行,然后handle3在执行
        disruptor.handleEventsWith(new Handle1(),new Handle2()).then(new Handle3());

        disruptor.start();

        CountDownLatch latch=new CountDownLatch(1);
        ExecutorService es = Executors.newFixedThreadPool((int)latch.getCount());
        for (long i = 0; i < latch.getCount(); i++) {
            //发送数据
            es.submit(new OrderEventTranslateProducer(disruptor,latch));
        }
        latch.await();
        es.shutdown();
        disruptor.shutdown();
        executorService.shutdown();

    }
}

使用EventTranslator来发送事件,不用手动的处理sequence。更加便捷

import com.lmax.disruptor.EventTranslator;
import com.lmax.disruptor.dsl.Disruptor;

import java.util.concurrent.CountDownLatch;

public class OrderEventTranslateProducer implements Runnable {

    private Disruptor<OrderEvent> disruptor;
    private CountDownLatch latch;

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


    @Override
    public void run() {
        disruptor.publishEvent(new OrderEventTranslator());
        latch.countDown();
    }
}

class OrderEventTranslator implements EventTranslator<OrderEvent> {
    @Override
    public void translateTo(OrderEvent event, long sequence) {
    }
}

创建3个消费者

import com.lmax.disruptor.EventHandler;
import com.lmax.disruptor.WorkHandler;

import java.util.Random;

public class Handle1 implements EventHandler<OrderEvent>,WorkHandler<OrderEvent> {

    @Override
    public void onEvent(OrderEvent event) throws Exception {
        Thread.sleep(1000);
        long v= new Random().nextLong()*9999;
        event.setValue(new Random().nextLong()*9999);
        System.out.println("线程:"+Thread.currentThread().getName()+",设置价格:"+v);
    }


    @Override
    public void onEvent(OrderEvent event, long sequence, boolean endOfBatch) throws Exception {
        this.onEvent(event);
    }
}
import com.lmax.disruptor.EventHandler;
import com.lmax.disruptor.WorkHandler;

import java.util.Random;

public class Handle2 implements EventHandler<OrderEvent>, WorkHandler<OrderEvent> {

    @Override
    public void onEvent(OrderEvent event, long sequence, boolean endOfBatch) throws Exception {
        this.onEvent(event);
    }
    @Override
    public void onEvent(OrderEvent event) throws Exception {
        Thread.sleep(1000);
        String name = Handle2.getName();
        event.setName(name);
        System.out.println("线程:"+Thread.currentThread().getName()+",设置name:"+name);
    }

    public static String getName(){
        String str="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        Random random1=new Random();
        //指定字符串长度,拼接字符并toString
        StringBuffer sb=new StringBuffer();
        for (int i = 0; i < 6; i++) {
            //获取指定长度的字符串中任意一个字符的索引值
            int number=random1.nextInt(str.length());
            //根据索引值获取对应的字符char
            char charAt = str.charAt(number);
            sb.append(charAt);
        }
        String str1 = sb.toString();
        return str1;
    }
}

import com.lmax.disruptor.EventHandler;
import com.lmax.disruptor.WorkHandler;

public class Handle3 implements EventHandler<OrderEvent>, WorkHandler<OrderEvent> {

    @Override
    public void onEvent(OrderEvent event, long sequence, boolean endOfBatch) throws Exception {
        this.onEvent(event);
    }
    @Override
    public void onEvent(OrderEvent event) throws Exception {
        System.out.println("线程:"+Thread.currentThread().getName()+",value:"+event.getValue()+",name:"+event.getName());
    }
}

如果是菱形操作的话,handle1和handle2并行执行,然后handle3在执行
在这里插入图片描述
在这里插入图片描述

源码分析

以单个生产类型ProducerType.SINGLE

通过 ringBuffer.next()找到下一个位置。

volatile字段(cursor)的写操作创建了一个内存屏障,这个屏障将刷新所有缓存里的值(缓存失效).
消费者获取RingBuffer序列号,涉及到读冲突的缓存失效,C2在C1之后,C2拿到C1更新过的序列号之后,C2才能获取next序列号。内存屏障保证了他们之前的执行顺序,消费者总能获取最新的序列号

内存屏障作为另一个CPU级的指令,没有锁那样大的开销,volatile意味着你不用加锁,就能让获得性能的提升

    @Override
    public long next(int n)
    {
        if (n < 1)
        {
            throw new IllegalArgumentException("n must be > 0");
        }

        //初始值nextValue=-1,语义级别,下一次的可用序号
        long nextValue = this.nextValue;
        //下一个序号
        long nextSequence = nextValue + n;
        //wrapPoint 用于判断当前的序号有没有绕过整个ringBuffer容器的大小
        long wrapPoint = nextSequence - bufferSize;
        //这个cachedGatingSequence 目的就是不要每次都获取消费者最小序号,用一个缓存去接收,只有下面If条件满足了,才会进行赋值
        long cachedGatingSequence = this.cachedValue;

        if (wrapPoint > cachedGatingSequence || cachedGatingSequence > nextValue)
        {
            //内存屏障 volatile字段 
            cursor.setVolatile(nextValue);  // StoreLoad fence

           //最小的消费者的序号
            long minSequence;
            //如果生产者的序号大于消费者中最小的序号,就进行自旋操作
            while (wrapPoint > (minSequence = Util.getMinimumSequence(gatingSequences, nextValue)))
            {
                LockSupport.parkNanos(1L); // TODO: Use waitStrategy to spin?
            }

            this.cachedValue = minSequence;
        }

        this.nextValue = nextSequence;

        // 返回下个可用的序号
        return nextSequence;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值