Disruptor(三)运行控制

1、线程池管理

Disruptor的带有Executor的构造方法都被声明为过期的,只保留了传入ThreadFactory的构造方法:

 两个传入ThreadFactory的构造方法,内部使用了固定的com.lmax.disruptor.dsl.BasicExecutor:

 

BasicExecutor只是简单的创建一个运行的线程,并放入一个线程队列中,没有任务队列的管理,应该是Disruptor推荐用这种简单的形式,线程池中不需要任务队列,使用RingBuffer做为任务队列缓存处理任务即可。

2、每个事件同时被多重处理

如果每个事件需要同时被多重处理,那么采用disruptor.handleEventsWith方法传入EventHandler数组,通常各个EventHandler是不同的,用于对事件进行不同方面的并行处理。每个EventHandler被包装在一个 EventProcessor中,每个EventProcessor关联一个线程。每个事件被同时传递给所有的EventHandler并行处理。

线程池中的线程数量取决于EventProcessor的数量,而EventProcessor的数量取决于传入的EventHandler数量:

public final EventHandlerGroup<T> handleEventsWith(final EventHandler<? super T>... handlers)

如果handleEventsWith后面级联多个then(handlers)方法,那么线程池的大小是所有EventHandler的总数。

handleEventsWith方法调用createEventProcessors来创建事件处理器,Disruptor默认使用BatchEventProcessor,BatchEventProcessor每次会取到小批量的事件进行串行处理(参见BatchEventProcessor的private void processEvents()方法)。

EventProcessor绑定的线程只负责从RingBuffer中获取数据,并调用EventHandler,默认情况下EventHandler也在该线程中执行,也就是业务处理和从RingBuffer中获取数据用了相同的线程。小批量事件在BatchEventProcessor被串行执行,要一个事件处理完之后才会继续处理下一个事件。

如果EventHandler中需要有创建资源和释放资源的操作,那么要实现LifecycleAware接口,用于在onStart()方法中创建资源,并在onShutdown()方法中释放资源。onStart()方法在第一个事件到达前被调用,onShutdown()方法在RingBuffer中的数据被处理完之后,线程停止前被调用。

3、多线程并行竞争处理事件

如果希望有多个事件消费者,每个消费者竞争消费不同的事件,那么要使用disruptor.handleEventsWithWorkerPool(final WorkHandler<T>... workHandlers)方法,通常workHandlers中的每个WorkHandler是相同类型的实例。每个WorkHandler被包装在一个WorkProcessor中,每个WorkProcessor关联一个线程。每个事件被传递给其中的一个WorkHandler处理。

线程池中的线程数量取决于WorkerPool中的WorkProcessor的数量,而WorkProcessor的数量取决于创建WorkerPool时传入的WorkHandler数量

如果WorkHandler中需要有创建资源和释放资源的操作,那么要实现LifecycleAware接口,用于在onStart()方法中创建资源,并在onShutdown()方法中释放资源。onStart()方法在第一个事件到达前被调用,onShutdown()方法在RingBuffer中的数据被处理完之后,线程停止前被调用。

4、生产者提交数据

生产提交数据建议使用RingBuffer的publishEvent或者tryPublishEvent方法,publishEvent方法在RingBuffer无空闲位时会一直等待,而tryPublishEvent在RingBuffer无空闲位时会返回false。

在实际应用开发中,建议使用tryPublishEvent,然后自己控制超时策略,避免生产者一直等待无法退出。

5、启动

调用Disruptor的RingBuffer<T> start()方法启动。

对应每个WorkProcessor、EventProcessor会创建一个线程,该线程驱动WorkProcessor、EventProcessor从RingBuffer中获取数据,WorkProcessor获取到数据之后调用WorkHandler处理数据,EventProcessor获取到数据之后调用EventHandler处理数据。

6、停止

调用Disruptor的void shutdown(final long timeout, final TimeUnit timeUnit) throws TimeoutException,或者public void shutdown()停止。

调用shutdown之后,Disruptor会拒绝把数据放入RingBuffer,并等待RingBuffer中的数据被所有的WorkProcessor、EventProcessor处理完成,然后再停止WorkProcessor、EventProcessor。

该方法不会停止executor,也不会等待processor线程的最终终止状态。

7、异常处理

如果EventHandler.onEvent方法抛出异常,那么EventProcessor会调用Disruptor中注册的ExceptionHandler的void handleEventException(Throwable ex, long sequence, T event)方法进行处理。

如果没有注册自定义的ExceptionHandler,那么会使用Disruptor默认的FatalExceptionHandler,该异常处理器会抛出RuntimeException,并导致EventProcessor的线程终止,EventProcessor进入IDLE状态,不再从RingBuffer中获取数据进行处理。

在正式的应用开发中,建议注册自定义的异常处理器,并且在自定义的异常处理器中不再抛出任何异常,保障EventProcessor的关联线程始终处于活跃状态。或者在自定义的EventHandler中不向Disruptor抛出任何异常,所有的异常在EventHandler中内部处理掉。

设置全局的异常处理器:

调用Disruptor的方法void setDefaultExceptionHandler(final ExceptionHandler<? super T> exceptionHandler)

可以为不同的EventHandler设置不同的异常处理器,替换所关联的全局异常处理器:

disruptor.handleExceptionsFor(eventHandler).with(exceptionHandler)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

kingspider-sh

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

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

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

打赏作者

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

抵扣说明:

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

余额充值