类 DisruptorEventLoop<T extends IAgentEvent>

java.lang.Object
cn.wjybxx.concurrent.AbstractEventLoop
cn.wjybxx.concurrent.DisruptorEventLoop<T>
所有已实现的接口:
EventLoop, EventLoopGroup, FixedEventLoopGroup, IExecutor, IExecutorService, IScheduledExecutorService, SingleThreadExecutor, AutoCloseable, Iterable<EventLoop>, Executor, ExecutorService, ScheduledExecutorService

public class DisruptorEventLoop<T extends IAgentEvent> extends AbstractEventLoop
基于Disruptor框架的事件循环。 1.这个实现持有私有的RingBuffer,可以有最好的性能。 2.可以通过nextSequence()publish(long)发布特殊的事件。 3.也可以让Task实现EventTranslator,从而拷贝数据到既有事件对象上。

关于时序正确性: 1.由于scheduledTaskQueue的任务都是从RingBuffer中拉取出来的,因此都是先于RingBuffer中剩余的任务的。 2.我们总是先取得一个时间快照,然后先执行scheduledTaskQueue中的任务,再执行RingBuffer中的任务,因此满足优先级相同时,先提交的任务先执行的约定 -- 反之,如果不使用时间快照,就可能导致后提交的任务先满足触发时间。

作者:
wjybxx date 2023/4/10
  • 构造器详细资料

  • 方法详细资料

    • state

      public final EventLoopState state()
      返回:
      EventLoop的当前状态
    • isRunning

      public final boolean isRunning()
      从接口复制的说明: EventLoop
      是否处于运行状态
    • isShuttingDown

      public final boolean isShuttingDown()
      从接口复制的说明: EventLoopGroup
      查询EventLoopGroup是否处于正在关闭状态。 正在关闭状态下,拒绝接收新任务,当执行完所有任务后,进入关闭状态。
      返回:
      如果该EventLoopGroup管理的所有EventLoop正在关闭或已关闭则返回true
    • isShutdown

      public final boolean isShutdown()
      从接口复制的说明: EventLoopGroup
      查询EventLoopGroup是否处于关闭状态。 关闭状态下,拒绝接收新任务,执行退出前的清理操作,执行完清理操作后,进入终止状态。
      返回:
      如果已关闭,则返回true
    • isTerminated

      public final boolean isTerminated()
      从接口复制的说明: EventLoopGroup
      是否已进入终止状态,一旦进入终止状态,表示生命周期真正结束。
      返回:
      如果已处于终止状态,则返回true
    • terminationFuture

      public final IFuture<?> terminationFuture()
      从接口复制的说明: EventLoopGroup
      返回等待线程终止的future。 返回的IFuture会在该Group管理的所有EventLoop终止后进入完成状态。
    • awaitTermination

      public final boolean awaitTermination(long timeout, @Nonnull TimeUnit unit) throws InterruptedException
      从接口复制的说明: EventLoopGroup
      等待EventLoopGroup进入终止状态 等同于在EventLoopGroup.terminationFuture()进行阻塞操作。
      参数:
      timeout - 时间度量
      unit - 事件单位
      返回:
      在方法返回前是否已进入终止状态
      抛出:
      InterruptedException - 如果在等待期间线程被中断,则抛出该异常。
    • runningFuture

      public final IFuture<?> runningFuture()
      从接口复制的说明: EventLoop
      等待线程进入运行状态的future future会在EventLoop成功启动的时候进入完成状态

      1.如果EventLoop启动失败,则Future进入失败完成状态 2.如果EventLoop未启动直接关闭,则Future进入失败完成状态 3.EventLoop关闭时,Future保持之前的结果

    • inEventLoop

      public final boolean inEventLoop()
      从接口复制的说明: EventLoop
      测试当前线程是否是Executor所在线程。 主要作用: 1.判断是否可访问线程封闭的数据。 2.防止死锁。

      警告:如果用户基于该测试实现分支逻辑,则可能导致时序错误,eg:

       
       	if(eventLoop.inEventLoop()) {
       	    doSomething();
        } else{
       	    eventLoop.execute(() -> doSomething());
        }
       
       
      假设现在有3个线程:A、B、C,它们进行了约定,线程A投递任务后,告诉线程B,线程B投递后告诉线程C,线程C再投递,以期望任务按照A、B、C的顺序处理。 在某个巧合下,线程C可能就是执行者线程,结果C的任务可能在A和B的任务之前被处理,从而破坏了外部约定的时序。

      该方法一定要慎用,它有时候是无害的,有时候则是有害的,因此必须想明白是否需要提供全局时序保证!

    • inEventLoop

      public final boolean inEventLoop(Thread thread)
      从接口复制的说明: EventLoop
      测试给定线程是否是当前事件循环线程 1.注意:EventLoop接口约定是单线程的,不会并发执行提交的任务,但不约定整个生命周期都在同一个线程上,以允许在空闲的时候销毁线程。 如果当前线程死亡,EventLoop是可以开启新的线程的,因此外部如果捕获了当前线程的引用,该引用可能失效。 (有一个经典的示例:Netty的GlobalEventExecutor) 2.该方法可用于任务检测是否切换了线程,以确保任务运行在固定的线程中
    • wakeup

      public final void wakeup()
      从接口复制的说明: EventLoop
      唤醒线程 如果当前EventLoop线程陷入了阻塞状态,则将线程从阻塞中唤醒;通常用于通知线程及时处理任务和响应关闭。 如果线程已停止,则该方法不产生影响
    • taskCount

      public int taskCount()
      当前任务数 注意:返回值是一个估算值!
    • getBarrier

      public ConsumerBarrier getBarrier()
      仅用于测试
    • getEventSequencer

      public EventSequencer<? extends T> getEventSequencer()
      EventLoop绑定的事件生成器 - 可用于发布事件
    • getAgent

      public EventLoopAgent<? super T> getAgent()
      EventLoop绑定的Agent(代理)
    • mainModule

      public EventLoopModule mainModule()
      从接口复制的说明: EventLoop
      事件循环的主模块 主模块是事件循环的外部策略实现,用于暴露特殊的业务接口 (Agent对内,MainModule对外,都是为了避免继承扩展带来的局限性)
    • execute

      public void execute(Runnable command)
      从接口复制的说明: IExecutor
      在将来的某个时间执行给定的命令。 命令可以在新线程中执行,也可以在池线程中执行,或者在调用线程中执行,这由Executor实现决定。 Executor.execute(Runnable)
      指定者:
      execute 在接口中 Executor
      指定者:
      execute 在接口中 IExecutor
      指定者:
      execute 在类中 AbstractEventLoop
      参数:
      command - 要执行的任务,注意ITask类型
    • execute

      public void execute(Runnable command, int options)
      从接口复制的说明: IExecutor
      在将来的某个时间执行给定的命令。 命令可以在新线程中执行,也可以在池线程中执行,或者在调用线程中执行,这由Executor实现决定。 Executor.execute(Runnable)

      任务的调度特征值 1.Executor需要感知用户任务的一些属性,以实现更好的管理。 2.选项可参考TaskOption。 3.该接口不应该测试任务的类型,应当以参数的options为准。

      指定者:
      execute 在接口中 IExecutor
      覆盖:
      execute 在类中 AbstractEventLoop
      参数:
      command - 要执行的任务
      options - 任务的调度特征值,见TaskOption
    • getEvent

      public final T getEvent(long sequence)
    • nextSequence

      public final long nextSequence()
      开放的特殊接口 1.按照规范,在调用该方法后,必须在finally块中进行发布。 2.事件类型必须大于等于0,否则可能导致异常 3.返回值为-1时必须检查
       
            long sequence = eventLoop.nextSequence();
            try {
                RingBufferEvent event = eventLoop.getEvent(sequence);
                // Do work.
            } finally {
                eventLoop.publish(sequence)
            }
       
      返回:
      如果申请成功,则返回对应的sequence,否则返回 -1
    • publish

      public final void publish(long sequence)
    • nextSequence

      public final long nextSequence(int size)
      1.按照规范,在调用该方法后,必须在finally块中进行发布。 2.事件类型必须大于等于0,否则可能导致异常 3.返回值为-1时必须检查
      
         int n = 10;
         long hi = eventLoop.nextSequence(n);
         try {
            long lo = hi - (n - 1);
            for (long sequence = lo; sequence <= hi; sequence++) {
                RingBufferEvent event = eventLoop.getEvent(sequence);
                // Do work.
            }
         } finally {
            eventLoop.publish(lo, hi);
         }
       
      参数:
      size - 申请的空间大小
      返回:
      如果申请成功,则返回申请空间的最大序号,否则返回-1
    • publish

      public final void publish(long lo, long hi)
      参数:
      lo - inclusive
      hi - inclusive
    • tickTime

      protected final long tickTime()
    • start

      public IFuture<?> start()
      从接口复制的说明: EventLoop
      主动启动EventLoop 一般而言,我们可以不主动启动EventLoop,在提交任务时会自动启动EventLoop,但如果我们需要确保EventLoop处于正确的状态才能对外提供服务时,则可以主动启动时EventLoop。 另外,通过提交任务启动EventLoop,是无法根据任务的执行结果来判断启动是否成功的。
      返回:
      EventLoop.runningFuture()
    • shutdown

      public void shutdown()
      从接口复制的说明: EventLoopGroup
      请求关闭 ExecutorService,不再接收新的任务。 ExecutorService在执行完现有任务后,进入关闭状态。 如果 ExecutorService 正在关闭,或已经关闭,则方法不产生任何效果。

      该方法会立即返回,如果想等待 ExecutorService 进入终止状态, 可以使用EventLoopGroup.awaitTermination(long, TimeUnit)EventLoopGroup.terminationFuture() 进行等待

    • shutdownNow

      @Nonnull public List<Runnable> shutdownNow()
      从接口复制的说明: EventLoopGroup
      JDK文档: 请求关闭 ExecutorService,尝试取消所有正在执行的任务,停止所有待执行的任务,并不再接收新的任务。 如果 ExecutorService 已经关闭,则方法不产生任何效果。

      该方法会立即返回,如果想等待 ExecutorService 进入终止状态,可以使用IExecutorService.awaitTermination(long, TimeUnit)IExecutorService.terminationFuture() 进行等待。

      在EventLoop架构下不保证标准的实现,只保证尽快的关闭。基于以下原因:

    • 1. 可能无法安全的获取所有的任务(EventLoop架构属于多生产者单消费者模型,会尽量的避免其它线程消费数据)
    • 2. 剩余任务数可能过多
    • 返回:
      may be empty。
    • newScheduledPromise

      public <V> IScheduledPromise<V> newScheduledPromise()
      从接口复制的说明: IScheduledExecutorService
      创建一个promise以用于任务调度 如果当前Executor是SingleThreadExecutor,返回的future将禁止在当前EventLoop上执行阻塞操作。
    • schedule

      public <V> IScheduledFuture<V> schedule(ScheduledTaskBuilder<V> builder)
      从接口复制的说明: IScheduledExecutorService
      为避免过多的参数和重载方法,我们通过Builder构建更为复杂的任务。
      类型参数:
      V - 任务的结果类型
      参数:
      builder - 任务构建器。
      返回:
      future
    • scheduleFunc

      public <V> IScheduledFuture<V> scheduleFunc(Function<? super IContext,V> task, IContext ctx, long delay, TimeUnit unit)
      从接口复制的说明: IScheduledExecutorService
      延迟指定时间后执行给定的任务
      参数:
      task - 要执行的任务
      ctx - 上下文-主要是取消令牌
    • scheduleAction

      public IScheduledFuture<?> scheduleAction(Consumer<? super IContext> task, IContext ctx, long delay, TimeUnit unit)
      从接口复制的说明: IScheduledExecutorService
      延迟指定时间后执行给定的任务
      参数:
      task - 要执行的任务
      ctx - 上下文-主要是取消令牌
    • schedule

      public IScheduledFuture<?> schedule(Runnable task, long delay, TimeUnit unit)
      从接口复制的说明: IScheduledExecutorService
      延迟指定时间后执行给定的任务
    • schedule

      public <V> IScheduledFuture<V> schedule(Callable<V> task, long delay, TimeUnit unit)
      从接口复制的说明: IScheduledExecutorService
      延迟指定时间后执行给定的任务
    • scheduleWithFixedDelay

      public IScheduledFuture<?> scheduleWithFixedDelay(Runnable task, long initialDelay, long delay, TimeUnit unit)
      从接口复制的说明: IScheduledExecutorService
      以固定延迟执行给定的任务(少执行了就少执行了)
    • scheduleAtFixedRate

      public IScheduledFuture<?> scheduleAtFixedRate(Runnable task, long initialDelay, long period, TimeUnit unit)
      从接口复制的说明: IScheduledExecutorService
      以固定频率执行给定的任务(少执行了会补-慎用)