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)