我是Scala的新手,并且拥有Java背景。
我面临的问题是我想在5分钟后执行一个功能。并且也可以随时取消。
在java中,我基本上会使用TimerTask,并将其设置为5分钟。如果我想取消,我只需拨打cancel
方法。好的是,我可以在Scala中使用该Java类。但是,由于我还在学习Scala,我只是想知道我是否错过了以更好的方式完成任务的更好方法。我遇到了Future
和Await.result
Scala课程,但我很难搞清楚。
有任何建议吗?
答案 0 :(得分:2)
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()
答案 1 :(得分:1)
通常,如果您使用某种框架,它将提供自己的抽象来处理计划任务。 Finagle有一个Timer
类,基于netty' s HashedWheelTimer
,例如,Akka有Scheduler
等。
(在整个应用程序中使用相同的调度框架是个好主意,因为这样可以更有效地使用资源)。
如果你只是在写"香草"没有任何框架的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)
等