请注意:虽然我喜欢使用Akka的Java API(这是我正在使用的)的解决方案,但我和#39;对任何有效的解决方案感到满意,并且可能想出如何将基于Scala的答案转换为Java-land。
我有一个拥有许多演员的Akka应用,其中两个是Fizz
和Buzz
。 Fizz
actor可以接受两种类型的消息:
StartNewTimerTask
;和ResetAllTimerTasks
Buzz
演员只接受DoItNow
消息。这些参与者与系统其余部分之间的消息流如下:
StartNewTimerTask
演员发送Fizz
消息Fizz
actor收到StartNewTimerTask
消息时,它会创建并启动一个新的异步/非阻塞计时器,尝试运行,例如8秒。如果计时器到达结尾(8秒),则会向DoItNow
演员发送Buzz
消息Fizz
演员可以接受任意数量的并发StartNewTimerTask
消息,因此可以"管理"可能同时有多个计时器,每个计时器都计入8秒的魔法数字。因此,如果其他20个演员在几秒钟内向StartNewTimerTask
演员发送Fizz
个消息,那么Fizz
演员将会管理" 20个非阻塞,独立的定时器同时。当这20个计时器中的每一个达到各自的8秒持续时间时,他们会向DoItNow
演员发送20条独立的Buzz
消息Fizz
演员收到ResetAllTimerTasks
条消息时,当前正在进行的任何计时器"将被中断/取消(以便他们停止倒计时到8秒的持续时间,从而阻止他们向DoItNow
发送Buzz
消息。因此,借用上面的示例,如果时间t=1
和t=3
Fizz
行为者收到了20条StartNewTimerTask
条消息,那么t=10
或许可能有14条消息DoItNow
计时器会过去并发出Fizz
条消息,也许还有6条消息正在进行中。如果在确切时刻ResetAllTimerTasks
收到Buzz
消息,则会阻止这6个定时器发送和触发消息,因此在此示例DoItNow
中只会收到14 TimerTask
消息我知道Java 8 API(没有Akka)主张扩展Timer#scheduleAtFixedRate
并将这些任务提交到// 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完全冲突或如果有更好的方法来使用Akka API实现此功能。到目前为止我最好的尝试:
def sum_odd_n(n):
while n<2*n: # n will always be less than ('<') 2*n. For eg, if n=5, 5<10.
sum = 0 # you are resetting the sum at every iteration. We need to take this outside.
if n%2==1:
sum = sum+n
return (sum)
但是,我不认为我正确管理计时器或充分发挥Akka调度程序/计时器API的潜力。 有什么想法吗?
答案 0 :(得分:1)
考虑避免使用Java Timer
API以支持刚刚与Akka 2.5.4一起发布的新actor timer功能。演员计时器允许演员使用一个或多个与其生命周期相关联的内部计时器来定期向自己发送消息。要在Java中访问此功能,只需将Fizz
actor更改为扩展AbstractActorWithTimers
。
以下示例位于Scala中(在Scala中,混合使用Timers
特征):
object Fizz {
private case object SendToBuzz
}
class Fizz(buzz: ActorRef) extends Actor with Timers {
import Fizz._
def receive = {
case StartNewTimerTask =>
val uuid = java.util.UUID.randomUUID
timers.startPeriodicTimer(uuid, SendToBuzz, 8.seconds)
case ResetAllTimerTasks =>
timers.cancelAll()
case SendToBuzz =>
buzz ! DoItNow
}
}
Fizz
actor处理StartNewTimerTask
消息时,它会启动一个新的计时器,该计时器会向SendToBuzz
发送self
消息(即{{1}演员)每八秒钟。Fizz
处理Fizz
消息时,它会向SendToBuzz
演员发送DoItNow
消息。Buzz
处理Fizz
消息时,它会取消所有计时器。 ResetAllTimerTasks
,则会自动取消所有计时器。