10.Disruptor 单机高并发

Disruptor

    定义:
    1.Disruptor叫无锁、高并发、环形Buffer
    2.直接覆盖旧数据,降低GC频率,用于生产者和消费者模式;
    3.观察者模式:消费者观察队列里边有没有东西,有的话立马拿出来消费
核心:
    核心是一个环形的buffer
等待策略:
    原理:生产者多,消费者来不及消费,生产者生产的就会执行等待策略
    等待策略有8种,常用的是BlockingWait
消费者异常处理:
    默认:disruptor.setDefaultExceotionHandle()
    覆盖:disruptor.handleExceptionsFor().with()
    
    disruptor.handleExceptionsFor(消费者).with(new ExceptionHandle<LongEvent>(){
        1.handleEventException 异常的时候直接打印出来
        2.handleOnStartException 启动的时候出异常
        3.handleOnshutdownException 停止的时候出异常
    })
ConcurrentLinkedQueue 与 Disruptor对比
ConcurrentLinkedQueue:
    1.里边是一个个链表,遍历起来没有数组快;
    2.维护一个head和end指针,头部加的时候需要枷锁,尾部取得时候也需要加锁;

Disruptor:
    1.环形长度为2的n次幂;
    2.维护一个位置Sequence,指向下一个可用的元素
    3.位置计算:用那个放入的数除以我们整个容量求余就可以,类似于麻将摇色子;
Disruptor开发步骤
1.定义Event-队列中要处理的元素;
2.定义Event工厂,用于填充队列;
    1.MyEventFactory实现EventFactiry<LongEvent>接口,重写newInstance方法,直接new LongEvent;
    2.工厂的作用:Disruptor初始化的时候会调用Event工厂,对ringBuffer进行内存的预分配,GC频率会降低;
    //factory:生产者工厂
    //buffersize:环的大小,2的n次幂
    //Exccutors.defaultThreadFactory:线程工厂
    Disruptor disruptor = new Disruptor<>(factory,buffersize,Exccutors.defaultThreadFactory);
    //连接hander
    disruptor.handEventswith(new MyEventHandler());
    //disruptor开始,所有的线程的开始
    disruptor.start();
    //获得环
    RingBuffer<LongEvent> ringBuffer =  disruptor.getRingBuffer();
    -------------------------------------------
    //第一种方法:
    //获取next指针
    Long sequence = disruptor.next();
    //在disruptor获取entry实例
    LongEvent event = ringBuffer.get(sequence);
    //给下个指针赋值
    event.set(8888L);
    //发布
    ringBuffer.publish(sequence);
    -------------------------------------------
    //第二种方法(直接赋值) :
    EventTranslator<LongEvent> translator1 = new EventTranslator<LongEvent>(){
        @override
        public void translateTo(LongEvent event,long sequence){
            event.set(8888L);
        }
    };
    ringBuffer.publishEvent(translator1);
    -------------------------------------------
    //第三种方法(一个参数):
    EventTranslatorOneAge<LongEvent,Long> translator2 = new EventTranslator<LongEvent,Long>(){
        @override
        public void translateTo(LongEvent event,long sequence,long l){
            event.set(l);
        }
    };
    ringBuffer.publishEvent(translator2,7777L);
    -------------------------------------------
    //第四种方法(两个个参数):
    EventTranslatorOneAge<LongEvent,Long,Long> translator3 = new EventTranslator<LongEvent,Long,Long>(){
        @override
        public void translateTo(LongEvent event,long sequence,long l1,long l2){
            event.set(l1+l2);
        }
    };
    ringBuffer.publishEvent(translator3,7777L,7777L);
    -------------------------------------------    
    //Lambda表达式以下
    ringBuffer.publishEvent((event,sequence) -> (event.set(7777L)));
    //一个参数
    ringBuffer.publishEvent((event,sequence,l) -> (event.set(l),7777L));  
    //两个参数
    ringBuffer.publishEvent((event,sequence,l1,l2) -> (event.set(l1+l2),7777L,7777L));   
3.定义EventHandler(消费者),处理容器中的元素;
ProducerType生产者线程模式
有两种模式:
1.product.MULTI(默认),多线程,多线程处理是要加锁的;
2.product.SINGLE,单线程,假如只有一个线程,应该把生产者定义为SINGLE,效率高,因为他不加锁;
等待策略 WaitStrateg
八种等待策略:
1.BlockingWaitStrategy(常用):
    通过线程堵塞方式,等待生产者唤醒,被唤醒后,在循环检查依赖的Sequence是否已经消费;
2.BusySpinWaitStrategy:
    线程一直自旋等待,可能比较消耗CUP;
3.LiteBlockingWaitStratege:
    线程阻塞等待生产者唤醒,与BlockingWaitStrategy相比,区别在SignalNeeded.getAndSet,如果两个线程同时访问一个访问waitfor,一个访问signalALL时,可以减少LOCK加锁次数;
4.LiteTimeoutBlockingWaitStrategy:
    与LiteBlockingWaitStratege相比,设置了阻塞时间,超过时间后抛出异常;
5.PhasedBackoffWaitStrategy:
    根据时间参数和传入的等待策略来决定使用哪种等待策略
6.TimeoutBlockingWaitStrategy:
    相比BlockingWaitStrategy相比,设置了阻塞时间,超过时间后抛出异常;
7.YieldingWaitStrategy(常用):
    尝试100次,然后Thread,yield()让出CUP;
8.SleepingWaitStrategy(常用):
    sleep;

BlockingWaitStrategy满了就等着;
SleepingWaitStrategy满了就睡一觉,醒了看能不能继续执行
; 
YieldingWaitStrategy让出CUP,让消费者赶紧消费,消费完了之后再回来看能不能在继续执行生产了;

一般YieldingWaitStrategy效率是最高的;
消费者异常处理
上边已总结
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值