disruptor第三弹(手撕第三章)

前言:这一章东西,可能突然有点多,我还特意少些了一点,免得东西太多,大家混乱了。本来很多东西我可以把源码那里搬过来,但我想想,这样就缺少了手撕的感觉。有可能我没搬过来,读者再去看源码就会发现原来,那样写会更好。多一点思考,比什么都重要,虽然是手撕,但我也希望读者是带着思考去想的。而且我这些手撕是基于单线程的。单的手撕完之后,我们再继续增加一些难度,多线程,然后基于安全考虑。

 

前面说了,消费者要异步消费。而不是我们手动去感知生产者生产东西了,我们去拿来消费。上代码:

 

public interface EventHandler<T>
{
    void onEvent(T event, long sequence) throws Exception;
}

 

public class StudentEventHandler implements EventHandler<Student> {
    @Override
    public void onEvent(Student event, long sequence) throws Exception {
        System.out.println("我进行异步消费了:"+event.getName());
    }
}

新增消费者的处理类,虽然是异步消费,那我们也要告诉异步的线程怎么去消费生产的东西

 

public interface EventProcessor  extends Runnable{
    //添加什么东西呢,请稍后
}
public class BatchEventProcessor<T> implements EventProcessor {

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

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

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

    /**
     * 缺少知晓生产者,生产到哪里了
     * 这里只拿了条消费者进行消费
     */
    @Override
    public void run() {
        long nextSequence = this.sequence.get() + 1L;
        T t = (T)this.objects[(int)nextSequence];
        try {
            while(true) {
                eventHandler.onEvent(t, nextSequence);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 这两个类的作用是啥???

刚才说了,我们要异步消费,那就需要有一个异步的线程去调用我们的消费工厂

/**
 * @Description:  
 * 这个类型需要后面大改造的,
 * 现在只是粗略的实现
 */
public class Sequence {
    private   long value;


    public Sequence() {
        this(-1L);
    }

    public Sequence(long initialValue) {
        value=initialValue;
    }
    public long get() {
        return this.value;
    }
    public void set(long value) {
        this.value=value;
    }
}

还需要一个消费的指针,明明就一个字段为什么要包装成类呢,因为只有类才能进行值传递。

 

然后:我们在再之前的 DisMain进行方法添加

/**
     * 消费者
     */
    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);
           if( this.processorList==null){
               this.processorList = new ArrayList<>();
           }
            this.processorList.add(batchEventProcessor);
        }
    }

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

 

就添加以上代码,把我们的消费工厂传入线程里,一个处理方法就是一个线程,当然,我们还要把环对象传入进去。这样才能知道生产者生产了哪些,然后才能进行消费。这里start方法就是启动相应消费方法的线程。

 

 

然后我们写个Main函数:

public class App2
{
    public static void main( String[] args )
    {

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


        disMain.start();

        Student stu = new Student();
        stu.setId(1);
        stu.setName("test");
        EventTranslatorOneArg translator = new StudentEventTranslator();
        disMain.put(translator,stu);
    }
}

 

细心的铜学,可能发现以上有一个问题

就是 消费线程里,直接拿环里的数据进行消费,但他完全不知道消费者消费到哪里了。就蠢蠢的一直消费。所以这里还缺少一个消费者得知道生产者生产到哪里了。

这里可能有人就想到了,刚刚不是有一个对象Sequence嘛,我只要在DisMain里面维护一个这样对象,生产的时候往里面数字递增,然后初始化消费线程的时候(就是初始化BatchEventProcessor),把这个对象传进去,那每个消费者不是拿到这个对象了嘛。确认这样可行,但这样可有一个缺陷。下一章我先按这个想法实现,然后再告诉各位它的缺陷

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值