如何安排在给定条件为真后结束的定期作业?
How to schedule a periodic job that ends after given condition is true?
我查看了 akka scheduler and the example here,它允许我安排周期性和单一任务。我需要创建一个具有以下签名的方法:
def doWhile(fn: => Unit, whileFn: => Boolean, period:Long) = {
// while whileFn evaluates to true, repeat fn every period millisecs
}
我可以将 fn
包装在另一个方法 fnNew
中,该方法计算 whileFn
并在为真时执行 fn
。然后我可以安排 fnNew
定期执行。但这似乎是一个糟糕的黑客攻击。我希望 fnNew
在 whileFn
计算为假时成为 "unscheduled"。正确的做法是什么?
编辑:我想避免使用显式参与者,并希望避免使用共享状态,如以下代码所示:
def doRegularly(fn: => Unit, periodMillis:Long) =
scheduler.schedule(0 seconds, periodMillis milliseconds)(fn)
def doWhile(fn: => Unit, whileFn: => Boolean, period:Long) = {
var c:Option[Cancellable] = None
c = Some(doRegularly(
if (whileFn) fn
else {
if (c.isDefined) c.get.cancel
}, period))
}
(具有共享值 c
)
从 docs 开始,您可以使用 cancel
//This will schedule to send the Tick-message
//to the tickActor after 0ms repeating every 50ms
val cancellable =
system.scheduler.schedule(0 milliseconds,
50 milliseconds,
tickActor,
Tick)</p>
<p>//This cancels further Ticks to be sent
cancellable.cancel()
</pre>
schedule
方法 returns 具有取消方法的类型 Cancellable
的对象。
我不确定,您打算如何使用 whileFn
,但只要它 returns 为假,就调用 Cancellable
对象上的取消方法。
我认为您可以利用 scheduleOnce
来完成您想要的 w/o 在 doWhile
的定义中共享状态。如果您这样定义 doWhile
:
def doWhile(fn: => Unit, whileFn: => Boolean, duration:FiniteDuration)(implicit sys:ActorSystem) {
if (whileFn){
fn
sys.scheduler.scheduleOnce(duration)(doWhile(fn, whileFn, duration))(sys.dispatcher)
}
}
然后你可以,例如,用下面的代码调用它:
implicit val system = ActorSystem("SchedTest")
var count = 1
doWhile(printAndInc, count <= 10, 1 second)
def printAndInc{
println(s"count is $count")
count += 1
}
如果你运行上面的代码,你会看到它打印出数字 1 到 10,中间有一个停顿。
我查看了 akka scheduler and the example here,它允许我安排周期性和单一任务。我需要创建一个具有以下签名的方法:
def doWhile(fn: => Unit, whileFn: => Boolean, period:Long) = {
// while whileFn evaluates to true, repeat fn every period millisecs
}
我可以将 fn
包装在另一个方法 fnNew
中,该方法计算 whileFn
并在为真时执行 fn
。然后我可以安排 fnNew
定期执行。但这似乎是一个糟糕的黑客攻击。我希望 fnNew
在 whileFn
计算为假时成为 "unscheduled"。正确的做法是什么?
编辑:我想避免使用显式参与者,并希望避免使用共享状态,如以下代码所示:
def doRegularly(fn: => Unit, periodMillis:Long) =
scheduler.schedule(0 seconds, periodMillis milliseconds)(fn)
def doWhile(fn: => Unit, whileFn: => Boolean, period:Long) = {
var c:Option[Cancellable] = None
c = Some(doRegularly(
if (whileFn) fn
else {
if (c.isDefined) c.get.cancel
}, period))
}
(具有共享值 c
)
从 docs 开始,您可以使用 cancel
//This will schedule to send the Tick-message //to the tickActor after 0ms repeating every 50ms val cancellable = system.scheduler.schedule(0 milliseconds, 50 milliseconds, tickActor, Tick)</p> <p>//This cancels further Ticks to be sent cancellable.cancel() </pre>
schedule
方法 returns 具有取消方法的类型Cancellable
的对象。 我不确定,您打算如何使用whileFn
,但只要它 returns 为假,就调用Cancellable
对象上的取消方法。
我认为您可以利用 scheduleOnce
来完成您想要的 w/o 在 doWhile
的定义中共享状态。如果您这样定义 doWhile
:
def doWhile(fn: => Unit, whileFn: => Boolean, duration:FiniteDuration)(implicit sys:ActorSystem) {
if (whileFn){
fn
sys.scheduler.scheduleOnce(duration)(doWhile(fn, whileFn, duration))(sys.dispatcher)
}
}
然后你可以,例如,用下面的代码调用它:
implicit val system = ActorSystem("SchedTest")
var count = 1
doWhile(printAndInc, count <= 10, 1 second)
def printAndInc{
println(s"count is $count")
count += 1
}
如果你运行上面的代码,你会看到它打印出数字 1 到 10,中间有一个停顿。