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

时间:2017-07-04 14:15:38

标签: scala scheduled-tasks delay

我是Scala的新手,并且拥有Java背景。

我面临的问题是我想在5分钟后执行一个功能。并且也可以随时取消。

在java中,我基本上会使用TimerTask,并将其设置为5分钟。如果我想取消,我只需拨打cancel方法。好的是,我可以在Scala中使用该Java类。但是,由于我还在学习Scala,我只是想知道我是否错过了以更好的方式完成任务的更好方法。我遇到了FutureAwait.result Scala课程,但我很难搞清楚。

有任何建议吗?

2 个答案:

答案 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)