disruptor第三弹(手撕第四章)

前言:之前说了,先按照上一章结尾所说去实现。消费线程里持有生产者的生产指针。

上代码: 

package com.wm;

import com.wm.factory.EventFactory;
import com.wm.factory.EventHandler;
import com.wm.factory.EventTranslatorOneArg;
import com.wm.main.Sequence;
import com.wm.processor.BatchEventProcessor;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Date: 2019-09-23 14:59
 * @Description:
 */
public class DisMain<T> {

    /**
     * 存放的环形队列
     */
    private Object[] objects;

    /**
     * 尾部指针
     */
    private int tail;

    /**
     * 头部指针
     */
    private int head;

    /**
     * 环形大小
     */
    public int ringBuffSie;

    /**
     * 生产者的指针
     */
    private Sequence producer= new Sequence();

    /**
     * 消费者
     */
    private List<BatchEventProcessor> processorList;


    private ExecutorService executors = Executors.newCachedThreadPool();
    /**
     * 传入消费的工厂
     * @param eventHandlers
     */
    public final void  handleEventsWith(final EventHandler<? super T>... eventHandlers)
    {
        int i = 0;
        for(int eventHandlersLength = eventHandlers.length; i < eventHandlersLength; ++i) {
            EventHandler<? super T> eventHandler = eventHandlers[i];
            BatchEventProcessor<T> batchEventProcessor = new BatchEventProcessor(  eventHandler,this.objects,producer,ringBuffSie);
           if( this.processorList==null){
               this.processorList = new ArrayList<>();
           }
            this.processorList.add(batchEventProcessor);
        }
    }

    public void start() {
        for (BatchEventProcessor batchEventProcessor : processorList) {
            executors.execute(batchEventProcessor);
        }
    }


    public DisMain(int ringBuffSie, EventFactory eventFactory) {
        this.ringBuffSie = ringBuffSie;
        objects = new Object[ringBuffSie];
        for (int i = 0; i <ringBuffSie ; i++) {
            objects[i] =eventFactory.newInstance();
        }
    }
    /**
     * 判断环形是否为空
     *
     * @return
     */
    public boolean isEmpty() {
        if (tail == head) {
            return true;
        }
        return false;
    }
    public boolean put(T obj){
        if(isFull()){
            return false;
        }else{
            objects[tail%ringBuffSie]=obj;
            tail++;
            return true;
        }
    }

    public <A> boolean put(EventTranslatorOneArg<T,A> arg,A arg0){
        if(isFull()){
            return false;
        }else{
            int position = tail%ringBuffSie;
            this.producer.set(tail);
            T t = (T)objects[position] ;
            arg.translateTo(t,tail,arg0);
            tail++;
            return true;
        }
    }


    public T get(){
        if(isEmpty()){
            return null;
        }else{
           Object obj =  objects[head];
            head++;
            return (T)obj;
        }
    }

    /**
     * 判断环形是否填满
     *
     * @return
     */
    public boolean isFull() {
        //现在的位置
        int nowPro = tail - ringBuffSie;
        if ((nowPro + 1) == head) {
            return true;
        }
        return false;
    }

    /**
     * 获取所有未消费的对象列表
     *
     * @return
     */
    public List<T> getObjects() {
        List<T> list = new ArrayList<>();
        if (isEmpty()) {
            //环形为空
            return null;
        }
        //生产跑了多少圈
        int proRoundSize = tail % ringBuffSie;
        //消费跑了多少圈
        int consumerRoundSize = head % ringBuffSie;

//        消费者和生产者跑了同样的圈数
        if (proRoundSize == consumerRoundSize) {
            for (int i = head + 1; i < tail; i++) {
                list.add((T)objects[i]);
            }
        } else if (proRoundSize > consumerRoundSize) {
            for (int i = head + 1; i < consumerRoundSize * ringBuffSie; i++) {
                list.add((T)objects[i - consumerRoundSize * ringBuffSie]);
            }
            int cn = tail - proRoundSize * ringBuffSie;
            for (int i = 0; i < cn; i++) {
                list.add((T)objects[i]);
            }
        }
        return list;
    }

}

看以上代码:新增

  1. 生产者的指针
  2. 初始化消费者线程的时候,把指针传进去
  3. put的时候,把tail赋值到生产者的指针里

 

public class BatchEventProcessor<T> implements EventProcessor {

    /**
     * 消费者,消费到哪里的指针
     */
    private final Sequence sequence = new Sequence(-1L);
    /**
     * 生产者的指针
     */
    private  Sequence producer;
    /**
     * 存放的环形队列
     */
    private Object[] objects;

    private int ringBuffSize;
    /**
     * 正真处理事件的回调接口。
     */
    private final EventHandler<? super T> eventHandler;

    public BatchEventProcessor(EventHandler<? super T> eventHandler,Object[] objects,Sequence producer,int ringBuffSize) {
        this.eventHandler = eventHandler;
        this.objects = objects;
        this.producer = producer;
        this.ringBuffSize = ringBuffSize;
    }

    @Override
    public void run() {
        long nextSequence = this.sequence.get() + 1L;

        try {
            while(true) {
                if(producer.get()>sequence.get()){
                    T t = (T)this.objects[(int)nextSequence%ringBuffSize];
                    eventHandler.onEvent(t, nextSequence);
                    sequence.set(nextSequence);
                    nextSequence++;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

看以上代码确实,好像解决了,但问题来了。我知道了生产者的位置,但生产者却不知道消费者的位置,所以万一生产者生产过快,覆盖了消费者怎么办,所以这时候需要一个中间类,这个类来记录消费者的指针和生产者的指针。来避免产生以上的问题。

 

 public static void main( String[] args )
    {

        DisMain<Student> disMain = new DisMain(16,new StudentFactory());
        StudentEventHandler studentEventHandler =new StudentEventHandler();
        disMain.handleEventsWith(studentEventHandler);


        disMain.start();

        EventTranslatorOneArg translator = new StudentEventTranslator();
        Student stu = new Student();
        for (int i = 0; i <20 ; i++) {
            stu.setId(i);
            stu.setName("test"+i);
            disMain.put(translator,stu);
        }

    }

可以试着运行下,最多消费到14,之后就不能运行了。因为isFull的原因

上面DisMain 的  isFull 也需要修改,因为我现在消费者的指针不在DisMain里面

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值