并发编程多线程基础(草稿7)-- disruptor框架

第四节(前三节是讲锁的,放到了上一个草稿中) disruptor概述
  • Disruptor是一个开源的并发框架,是一个高性能的异步处理框架,或者可以认为是最快的消息框架(轻量的JMS),也可以认为是一个观察者模式的实现,或者事件监听模式的实现。
  • 性能要高于BlockingQueue,BlockingQueue原理用的是悲观锁,disruptor用的是乐观锁。
  • disruptor是用事件监听实现的
第五节 disruptor的原理
  • disruptor最大的优点就是无锁
  • disruptor也叫做高性能的无锁队列。
  • disruptor底层使用的是CAS无锁机制。
  • disruptor是基于事件驱动源(观察者模式),BlockingQueue是生产者,消费者模式。

BlockingQueue是生产者生产的消息主动推送到队列容器中,消费者直接从队列容器中取数据;
disruptor是生产者产生的信息主动推送给ringbuffer(就是BlockingQueue中的队列容器),当ringbuffer中有数据的时候主动给消费者,不再是消费者去取了。

  • Disruptor的核心概念
    (1)ringbuffer:ringbuffer是一个环形的数组,disruptor用他来存储消息,而BlockingQueue底层用的是链表。环形的缓冲区,曾经RingBuffer是Disruptor中的最主要的对象,但从3.0之后,其职责被简化成了仅仅是通过Disruptor进行交换的数据(事件)进行存储和更新。在一些高级的场景中,RingBuffer可以由用户的自定义实现来完全代替。
    (2)SequenceDisruptor:通过顺序递增的序号来编号管理通过其进行交换的数据(事件),对数据(事件)的处理过程总是沿着序号逐个递增处理。一个Sequence用于跟踪标识某个特定的时间处理者的进度。虽然一个AtomicLong也可以用于标识进度,单定义Sequence来负责问题还有另一个目的:防止不同的Sequence之间的CPU缓存伪共享。
    Sequencer是Disruptor的真正核心,此接口有两个实现类,SingleProducerSequrncer,MultiProducerSequence,他们定义在生产者和消费者之间快速,正确的传递数据的并发算法。
    (3)Sequence Barrier:用于保持对RingBuffer的main published Sequence和Consumer依赖的其他Consumer的Sequence的引用。Sequence Barrier还定义了决定Consumer是否还有可处理的时间的逻辑。
    (4)Wait Strategy:定义了Consumer如何进行等待下一个时间的策略。(注意:Disruptor定义了多种不同的策略,针对不同的场景,提供了不一样的性能表现)
    (5)Event:在Disruptor的语义中。生产者和消费者之间进行交换的数据被称为事件。他不是一个被Distruptor定义的特定类型。而是由Disruptor的使用者定义并指定。
    (6)EventProcessor:EventProcessor持有特定的消费者(Consumer)的Sequence,并提供用于调用时间处理实现的时间循环。
    (7)EventHandler:Disruptor定义的事件处理接口,由用户实现,用于处理事件,是Consumer的真正实现。
    (8)Producer:即生产者,只是泛指调用Disruptor发布事件的用户代码,Disruptor没有定义特定的接口或类型。

  • RingBuffer是一个环形数组,长度必须是2的N次方,且该环形长度不能扩展长度,若长度过长,则依靠环形结构覆盖之前的数据。Sequence相当于是环形数组的下标,标记其在RingBuffer中的位置。

  • RingBuffer利用取模确定元素位置所在。

第六节和第七节 创建disruptor的生产端和消费端
package com.xiyou.mayi.thread5.testDisruptor;

/**
 * 定义事件event(就是消费者与发送者交互的数据)
 */
public class LongEvent {
    private Long value;

    public Long getValue() {
        return value;
    }

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


package com.xiyou.mayi.thread5.testDisruptor;

import com.lmax.disruptor.EventFactory;

/**
 * 需要让Disruptor为我们创建事件,我们同时声明了一个工厂来实例化Event对象
 */
public class LongEventFactory implements EventFactory<LongEvent> {
    @Override
    public LongEvent newInstance() {
        return new LongEvent();
    }
}

package com.xiyou.mayi.thread5.testDisruptor;


import com.lmax.disruptor.EventHandler;

/**
 * 事件的消费者,也就是一个事件处理器。这个事件处理器是事件监听
 */
public class LongEventHandler implements EventHandler<LongEvent> {
    @Override
    public void onEvent(LongEvent longEvent, long sequence, boolean endOfBatch) throws Exception {
        System.out.println("消费者: " + longEvent.getValue());
    }
}


package com.xiyou.mayi.thread5.testDisruptor;

import com.lmax.disruptor.RingBuffer;

import java.nio.ByteBuffer;

/**
 * 定义发送者
 */
public class LongEventProducer {

    private RingBuffer<LongEvent> ringBuffer;

    /**
     * 构造函数
     * @param ringBuffer
     */
    public LongEventProducer(RingBuffer<LongEvent> ringBuffer){
        this.ringBuffer = ringBuffer;
    }

    /**
     * 定义了生产者生产数据的方法,将生产的数据推送到RingBuffer中去
     * @param byteBuffer
     */
    public void onData(ByteBuffer byteBuffer){
        // 获取事件队列下标位置,即获取当前的事件应该放到ringBuffer的哪一个位置上
        long sequence = ringBuffer.next();
        try {
            // 取出空的队列,根据下标取出
            LongEvent longEvent = ringBuffer.get(sequence);
            // 给空队列赋值
            longEvent.setValue(byteBuffer.getLong(0));
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            System.out.println("发送者无论如何到发送数据");
            // 发送数据
            ringBuffer.publish(sequence);
        }
    }

}



package com.xiyou.mayi.thread5.testDisruptor;

import com.lmax.disruptor.EventFactory;
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.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 启动入口
 */
public class Main {
    public static void main(String[] args) {
        // 创建线程池,提供给consumer
        ExecutorService executor = Executors.newCachedThreadPool();
        // 创建Event工厂
        // 该工厂的作用就是定义一个事件
        EventFactory<LongEvent> eventFactory = new LongEventFactory();
        // 定义RingBuffer的大小,该大小只能是2的N次方
        int ringbuffer = 1024 * 1024;
        // 创建Disruptor
        Disruptor<LongEvent> disruptor = new Disruptor<LongEvent>(eventFactory, ringbuffer, executor,
                ProducerType.MULTI, new YieldingWaitStrategy());
        // 注册消费者,告诉disruptor发送给哪个消费者,支持多个消费者,消费者不是负载均衡,而是像订阅发布一样消费同一个ringbuffer中的事件
        disruptor.handleEventsWith(new LongEventHandler());
        // 启动消费者
        disruptor.start();
        // 创建RingBuffer容器
        RingBuffer<LongEvent> ringBuffer = disruptor.getRingBuffer();
        // 创建生产者
        LongEventProducer longEventProducer = new LongEventProducer(ringBuffer);
        // 指定缓冲区大小,nio发送数据
        ByteBuffer byteBuffer = ByteBuffer.allocate(8);
        for (int i = 0; i < 100; i++) {
            byteBuffer.putLong(0, i);
            longEventProducer.onData(byteBuffer);
        }
        // 关闭
        executor.shutdown();
        disruptor.shutdown();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值