Scala:延迟代码块执行或取消它



我对Scala很陌生,有Java的背景。

我面临的问题是我想在 5 分钟后执行一个函数。并且可以随时取消此操作。

在java中,我基本上会使用TimerTask,并将其设置为5分钟。如果我想取消,我只需调用cancel方法。好消息是,我可以在Scala中使用Java类。但是当我还在学习Scala时,我只是想知道我是否错过了以更好的方式实现这一目标的更好方法。我遇到了FutureAwait.resultScala 课程,但我很难弄清楚。

有什么建议吗?

scala 库中的Future不可取消。你要做的是实现某种条件,并确保你的"东西"只在条件为真的情况下运行。

您可能想查看monix.Task,这是可取消的:https://monix.io/docs/2x/eval/task.html

从他们的文档中:

import monix.eval.Task
import monix.execution.CancelableFuture
import concurrent.duration._
val task = Task(1 + 1).delayExecution(1.second)
val result: CancelableFuture[Int] =
task.runAsync
// If we change our mind
result.cancel()

通常,如果您使用某种框架,它将提供自己的抽象来处理计划任务。Finagle有一个Timer类,例如基于Netty的HashedWheelTimer,Akka有Scheduler,等等。 (最好在整个应用程序中使用相同的调度框架,因为这可以更有效地使用资源(。

如果你只是在没有任何框架的情况下编写"vanilla"scala代码,那么直接使用TimerTask并没有错,或者,也许,在它周围做一个小包装器,这样在scala代码中使用它就不会那么尴尬:

class FutureTask[T](f: => Future[T]) extends TimerTask {  
val promise = Promise[T]()
def run(): Unit = promise.completeWith(f)
override def cancel() = {
val result = super.cancel
if(result) promise.complete(Failure(new CancellationException))
result
}
}
object FutureTask {
implicit def toFuture[T](task: FutureTask[T]) = task.promise.future
def scheduleFlat[T](when: Duration)(f: => Future[T])(implicit timer: Timer = defaultTimer): FutureTask[T] = {
val task = new FutureTask(f)
timer.schedule(task, when.toMillis)
task          
}
def schedule[T](when: Duration)(f: => T)(implicit timer: Timer = defaultTimer, ctx: ExecutionContext): FutureTask[T] = 
scheduleFlat(when)(Future(f))(timer)
val defaultTimer = new java.util.Timer(true)
}

现在,您可以执行以下操作:

val someTask = FutureTask
.schedule(5 seconds) { println("Hello!") }
someTask.onComplete { result => println("Completed with " + result) }
someTask.cancel
Await.result(someTask, 2 seconds)

等。

最新更新