Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/actionscript-3/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 非阻塞计时器任务和Akka参与者_Java_Timer_Akka - Fatal编程技术网

Java 非阻塞计时器任务和Akka参与者

Java 非阻塞计时器任务和Akka参与者,java,timer,akka,Java,Timer,Akka,请注意:尽管我更喜欢使用Akka的Java API(我正在使用的)解决方案,但我对任何可行的解决方案都很满意,并且可能知道如何将基于Scala的答案转换为Java语言 我有一个Akka应用程序,有很多演员,其中两个是Fizz和Buzz。Fizz actor可以接受两种类型的消息: StartNewTimerTask;和 重置所有时间任务 Buzz actor只接受DoItNow消息。这些参与者与系统其余部分之间的消息流如下所示: 任何其他参与者,甚至是参与者系统之外的事件驱动组件,都可以随时向F

请注意:尽管我更喜欢使用Akka的Java API(我正在使用的)解决方案,但我对任何可行的解决方案都很满意,并且可能知道如何将基于Scala的答案转换为Java语言

我有一个Akka应用程序,有很多演员,其中两个是Fizz和Buzz。Fizz actor可以接受两种类型的消息:

StartNewTimerTask;和 重置所有时间任务 Buzz actor只接受DoItNow消息。这些参与者与系统其余部分之间的消息流如下所示:

任何其他参与者,甚至是参与者系统之外的事件驱动组件,都可以随时向Fizz参与者发送StartNewTimerTask消息 每次Fizz actor收到StartNewTimerTask消息时,它都会创建并启动一个新的异步/非阻塞计时器,该计时器将尝试运行8秒。如果计时器在8秒后结束,则会向Buzz actor发送DoItNow消息 Fizz参与者可以接受任意数量的并发StartNewTimerTask消息,因此,可以同时管理多个计时器,每个计时器都朝着8秒的神奇数字计数。因此,如果20个其他参与者在几秒钟内向Fizz参与者发送StartNewTimerTask消息,那么Fizz参与者将同时管理20个非阻塞、独立的计时器。当这20个计时器中的每一个达到各自的8秒时长时,它们会向Buzz actor发送20条独立的DoItNow消息 当Fizz actor收到ResetAllTimerTasks消息时,当前正在进行的任何计时器都将被中断/取消,从而停止倒计时到8秒的持续时间,从而阻止它们向Buzz发送DoItNow消息。因此,借用我们上面的例子,如果在t=1和t=3之间,Fizz参与者收到20条StartNewTimerTask消息,那么在t=10时,他们各自的计时器中可能有14条已经过去并触发了DoItNow消息,可能还有6条仍在进行中。如果此时Fizz收到ResetAllTimerTasks消息,它将阻止这6个计时器消失并触发消息,因此在本例中Buzz只接收14条DoItNow消息 我知道Java 8 API sans-Akka主张扩展TimerTask并将这些任务提交给TimerscheduleAtFixedRate方法,但我不确定这是否与Akka冲突,或者是否有更好的方法使用Akka API实现此功能。我迄今为止最好的尝试是:

// Groovy pseudo-code
class MyTimerTask extends TimerTask {
  @Inject
  ActorRef buzz

  @Override
  void run() {
    // No op!
  }

  void completeTask() {
    buzz.tell(new DoItNow(), null)
  }
}

class Fizz extends UntypedAbstractActor {
  @Inject
  Timer timer

  @Override
  void onReceive(Object message) {
    if(message in StartNewTimerTask) {
      timer.scheduleAtFixedRate(new MyTimerTask(), 0, 8 * 1000)
    } else if(message in ResetAllTimerTasks) {
      timer.cancel()
    }
  }
}

class Buzz extends UntypedAbstractActor {
  @Override
  void onReceive(Object message) {
    if(message in DoItNow) {
      // Do something super cool now...
    }
  }
}

但是,我认为我没有正确地管理计时器,也没有充分利用Akka调度器/计时器API的潜力。有什么想法吗?

考虑避开Java计时器API,转而使用刚刚随Akka 2.5.4发布的新功能。参与者计时器允许参与者使用与其生命周期相关的一个或多个内部计时器将周期性消息调度到自己。要在Java中访问此功能,只需将Fizz actor更改为extend

下面的示例是Scala中的Scala,混合在trait中:

物体嘶嘶作响{ 私有案例对象SendToBuzz } 类Fizzbuzz:ActorRef使用计时器扩展Actor{ 进口汽水_ def接收={ case StartNewTimerTask=> val uuid=java.util.uuid.randomUUID timers.startPeriodicTimeruuid,SendToBuzz,8.5秒 案例重置AllTimerTasks=> 计时器。全部取消 案例SendToBuzz=> 巴兹!快 } } 当Fizz actor处理StartNewTimerTask消息时,它会启动一个新的计时器,该计时器将每八秒钟向self(即Fizz actor)发送一条SendToBuzz消息。 当Fizz处理SendToBuzz消息时,它会向Buzz参与者发送DoItNow消息。 Fizz处理ResetAllTimerTasks消息时,会取消所有计时器。 如果Fizz重新启动或停止,其所有计时器将自动取消。