disruptor并发框架的使用

佐手、 提交于 2020-02-28 06:58:22

springboot 项目中disruptor并发框架的使用

1、导包

<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-disruptor-starter</artifactId>
    <version>2.25.0</version>
</dependency>

2、一个数据封装类

/**
 * 数据封装类
 * Created by liunanhua on 2018/7/19.
 */
public class LongEvent {

    private long value;

    public long getValue() {
        return value;
    }

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

数据封装类工厂

/**
 * LongEven工厂
 * Created by liunanhua on 2018/7/19.
 */
public class LongEventFactory implements EventFactory<LongEvent> {

    @Override
    public LongEvent newInstance() {
        return new LongEvent();
    }
}

3、一个生产者

import com.lmax.disruptor.EventTranslatorOneArg;
import java.text.MessageFormat;

/**
 * 生产者
 * 事件转换
 * Created by liunanhua on 2018/7/19.
 */
public class LongEventTranslator implements EventTranslatorOneArg<LongEvent, Long> {

    @Override
    public void translateTo(LongEvent event, long sequence, Long data) {
        System.out.println(MessageFormat.format("生产者生产数据data = {0}, seq = {1}", data, sequence));
        event.setValue(data);
    }
}

4、一个或多个消费者  

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

/**
 * 消费者
 * EventHandler和WorkHandler的区别是前者不需要池化,后者需要池化。
 * Created by liunanhua on 2018/7/19.
 */
public class LongEventConsumer implements EventHandler<LongEvent>, WorkHandler<LongEvent> {

    @Override
    public void onEvent(LongEvent longEvent, long sequence, boolean endOfBatch) {
        this.onEvent(longEvent);
    }

    @Override
    public void onEvent(LongEvent longEvent) {
        long threadId = Thread.currentThread().getId(); // 获取当前线程id
        System.out.println("消费者[" + threadId +"]消费数据data = " + longEvent.getValue());
    }
}

5、使用方法

import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.YieldingWaitStrategy;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;
import java.nio.ByteBuffer;
import java.util.concurrent.ThreadFactory;

/**
 * 测试类
 * Created by liunanhua on 2018/7/19.
 */
public class DisruptorTest {

    public static void main(String[] args) throws Exception {
        //RingBuffer大小,必须是2的N次方
        int ringBufferSize = 1024 * 8;
        /**
         *BlockingWaitStrategy 是最低效的策略,但其对CPU的消耗最小并且在各种不同部署环境中能提供更加一致的性能表现
         *    WaitStrategy BLOCKING_WAIT = new BlockingWaitStrategy();
         *SleepingWaitStrategy 的性能表现跟BlockingWaitStrategy差不多,对CPU的消耗也类似,但其对生产者线程的影响最小,适合用于异步日志类似的场景
         *    WaitStrategy SLEEPING_WAIT = new SleepingWaitStrategy();
         *YieldingWaitStrategy 的性能是最好的,适合用于低延迟的系统。在要求极高性能且事件处理线数小于CPU逻辑核心数的场景中,推荐使用此策略;例如,CPU开启超线程的特性
         *    WaitStrategy YIELDING_WAIT = new YieldingWaitStrategy();
         */
        //创建disruptor
        Disruptor<LongEvent> disruptor = new Disruptor<LongEvent>(new LongEventFactory(),
                ringBufferSize,
                new ThreadFactory() {
                    @Override
                    public Thread newThread(Runnable r) {
                        return new Thread(r);
                    }
                },
                ProducerType.SINGLE,
                new YieldingWaitStrategy());

        //处理业务,连接消费事件方法,可多个消费者
        //disruptor.handleEventsWith(new LongEventConsumer());
        LongEventConsumer[] consumers = new LongEventConsumer[10];
        for (int i = 0; i < consumers.length; i++) {
            consumers[i] = new LongEventConsumer();
        }
        //使用handleEventsWithWorkerPool就可以完成不重复消费,使用handleEventsWith会重复消费。
        disruptor.handleEventsWithWorkerPool(consumers);

        //启动
        RingBuffer<LongEvent> ringBuffer = disruptor.start();
        ByteBuffer byteBuffer = ByteBuffer.allocate(8);
        for (long l = 0; l < 10; l++) {
            //生产数据
            long data = (long)(Math.random() * 1000d);
            byteBuffer.putLong(0, data);
            new LongEventProducer(ringBuffer).produceData(byteBuffer);//生产数据
        }
        disruptor.shutdown();//关闭 disruptor,方法会堵塞,直至所有的事件都得到处理;
    }
}

其他

事件转换器中生产数据

import com.lmax.disruptor.EventTranslatorOneArg;
import java.text.MessageFormat;
/**
 * 生产者
 * 事件转换
 * Created by liunanhua on 2018/7/19.
 */
public class LongEventTranslator implements EventTranslatorOneArg<LongEvent, Long> {

    @Override
    public void translateTo(LongEvent event, long sequence, Long data) {
        System.out.println(MessageFormat.format("生产者生产数据data = {0}, seq = {1}", data, sequence));
        event.setValue(data);
    }
}

测试

import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.YieldingWaitStrategy;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;
import java.util.concurrent.ThreadFactory;

/**
 * 测试类
 * Created by liunanhua on 2018/7/19.
 */
public class DisruptorTest {

    public static void main(String[] args) {
        //RingBuffer大小,必须是2的N次方
        int ringBufferSize = 1024 * 8;
        //创建disruptor
        Disruptor<LongEvent> disruptor = new Disruptor<LongEvent>(new LongEventFactory(),
                ringBufferSize,
                new ThreadFactory() {
                    @Override
                    public Thread newThread(Runnable r) {
                        return new Thread(r);
                    }
                },
                ProducerType.SINGLE,
                new YieldingWaitStrategy());

        //处理业务,连接消费事件方法,可多个消费者
        //使用handleEventsWithWorkerPool就可以完成不重复消费,使用handleEventsWith会重复消费。
        disruptor.handleEventsWithWorkerPool(consumers);

        //启动
        RingBuffer<LongEvent> ringBuffer = disruptor.start();
        for (long l = 0; l < 10; l++) {
            //生产数据
            long data = (long)(Math.random() * 1000d);
            ringBuffer.publishEvent(new LongEventTranslator(), data);
        }
        disruptor.shutdown();//关闭 disruptor,方法会堵塞,直至所有的事件都得到处理;
    }
}

 

使用handleEventsWithWorkerPool就可以完成不重复消费,使用handleEventsWith会重复消费
disruptor.handleEventsWithWorkerPool(consumers);
执行顺序
disruptor.after(new LongEventSaveConsumer()).handleEventsWith(new LongEventSmsConsumer()).then(new LongEventSmsConsumer2());

代码:https://gitee.com/lion123/springboot-thread-demo

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!