内存队列Disruptor

系列文章目录



前言

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。
在这里插入图片描述
Disruptor 是一个开源的高性能内存队列,由英国外汇交易公司 LMAX 开发的,获得了 2011 年的 Oracle 官方的 Duke’s Choice Awards(Duke 选择大奖)。

Disruptor 提供的功能类似于 Kafka、RocketMQ 这类分布式队列,不过,其作为范围是 JVM(内存)。


Github 地址:https://github.com/LMAX-Exchange/disruptor

官方教程:https://lmax-exchange.github.io/disruptor/user-guide/index.html

Disruptor 解决了 JDK 内置线程安全队列的性能和内存安全问题。以下为官方给出的对比图:
在这里插入图片描述
参照官方示例,写一个HelloWorld工程,首先是引入相关依赖

<dependency>
    <groupId>com.lmax</groupId>
    <artifactId>disruptor</artifactId>
    <version>3.4.4</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

创建一个Event,我们可以理解为MQ中的消息体

package com.example.demo.mq;
import lombok.Data;
@Data
public class LogEvent {
    private String message;
    // 可以定义其他属性
}

创建LogEventFactory用于创建Event

package com.example.demo.mq;
import com.lmax.disruptor.EventFactory;
public class LogEventFactory implements EventFactory<LogEvent> {
    @Override
    public LogEvent newInstance() {
        return new LogEvent();
    }
}

创建Handler,这是负责处理消息的地方

package com.example.demo.mq;
import com.lmax.disruptor.EventHandler;
public class LogEventHandler implements EventHandler<LogEvent> {
    /**
     * 处理事件的 Handler
     * @param logEvent 待消费/处理的事件
     * @param sequence 正在处理的事件在环形数组(RingBuffer)中的位置
     * @param endOfBatch 表示这是否是来自环形数组(RingBuffer)中一个批次的最后一个事件(批量处理事件)
     */
    @Override
    public void onEvent(LogEvent logEvent, long sequence, boolean endOfBatch) {
        System.out.println(logEvent.getMessage());
    }
}

创建测试类

package com.example.demo;
import com.example.demo.mq.LogEvent;
import com.example.demo.mq.LogEventFactory;
import com.example.demo.mq.LogEventHandler;
import com.lmax.disruptor.BlockingWaitStrategy;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;
import org.junit.jupiter.api.Test;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
public class DisruptorTest {
    @Test
    public void test1() {
        int bufferSize = 1024;
        // 获取 Disruptor 对象
        // Disruptor<LogEvent> disruptor = new Disruptor<>(LogEvent::new, bufferSize, DaemonThreadFactory.INSTANCE);
        Disruptor<LogEvent> disruptor = getLogEventDisruptor();
        // 绑定处理事件的Handler对象
        // 以设置多个处理事件的 Handler,并且可以灵活的设置消费者的处理顺序,串行,并行都是可以的。
        disruptor.handleEventsWith(new LogEventHandler());
        // 下面的代码表示 Handler1 和 Handler2 是并行执行,最后再执行 Handler3
        // disruptor.handleEventsWith(new Handler1(), new Handler2()).handleEventsWith(new Handler3());
        // 启动 Disruptor
        disruptor.start();
        // 获取保存事件的环形数组(RingBuffer)
        RingBuffer<LogEvent> ringBuffer = disruptor.getRingBuffer();
        // 发布 5个 个事件
        for (int i = 1; i <= 5; i++) {
            try {
                // 初始化 Event,对其赋值
                ringBuffer.publishEvent((event, sequence, buffer) -> event.setMessage("这是日志消息 " + System.nanoTime()));
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        // 关闭 Disruptor
        disruptor.shutdown();
        // 模拟堵塞主线程不退出
        try {
            while (true) {
                Thread.sleep(5000);
            }
        } catch (Exception e) {
 
        }
    }
    private static Disruptor<LogEvent> getLogEventDisruptor() {
        // 创建 LogEvent 的工厂
        LogEventFactory logEventFactory = new LogEventFactory();
        // Disruptor 的 RingBuffer 缓存大小,环形缓冲器的大小,必须是2的幂
        int bufferSize = 1024;
        // 生产者的线程工厂
        ThreadFactory threadFactory = new ThreadFactory() {
            // 线程安全的计数类
            // https://www.javacui.com/Theory/691.html
            final AtomicInteger threadNum = new AtomicInteger(0);
            @Override
            public Thread newThread(Runnable r) {
                System.out.println("LogEventThread" + " [#" + threadNum.incrementAndGet() + "] 已创建");
                return new Thread(r, "LogEventThread" + " [#" + threadNum.incrementAndGet() + "]");
            }
        };
        //实例化 Disruptor
        return new Disruptor<>(
                logEventFactory, // 自定义的事件工厂
                bufferSize,      // 自定义的时间工厂
                threadFactory,   // 自定义的线程工厂。Disruptor的默认线程池是自定义的,我们只需要传入线程工厂即可。
                ProducerType.MULTI,          // 指定是单个事件发布者模式还是多个事件发布者模式
                new BlockingWaitStrategy()); // 阻塞等待策略
    }
}

运行程序,可以看到打印输出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java毕设王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值