斯卡拉 - ScheduledFuture(Scala - ScheduledFuture)

2019-09-01 20:52发布

我想在斯卡拉实施计划的未来。 我想它等待特定的时间,然后执行体。 到目前为止,我试过以下,简单的方法

val d = 5.seconds.fromNow

val f = future {Await.ready(Promise().future, d.timeLeft); 1}

val res = Await.result(f, Duration.Inf)

但我正在逐渐对未来的TimeoutExcpetion。 这是即使是正确的做法,或者我应该简单地使用从Java ScheduledExecutor?

Answer 1:

你可以更改您的代码是这样的:

val d = 5.seconds.fromNow
val f = Future {delay(d); 1}
val res = Await.result(f, Duration.Inf)

def delay(dur:Deadline) = {
  Try(Await.ready(Promise().future, dur.timeLeft))
}

但我不会推荐它。 这样一来,你会在将来被阻塞(阻塞,以等待Promise永远不会完成),我认为在阻止ExecutionContext大大气馁。 我要么考虑使用java的安排执行程序,你说或者你可以考虑使用作为阿卡@ alex23建议。



Answer 2:

阿卡有akka.pattern:

def after[T](duration: FiniteDuration, using: Scheduler)(value: ⇒ Future[T])(implicit ec: ExecutionContext): Future[T]

“返回将与指定的时间后,所提供的价值的成功或失败来完成scala.concurrent.Future。”

http://doc.akka.io/api/akka/2.2.1/#akka.pattern.package



Answer 3:

没有什么可以做出来单独使用标准库的开箱。 对于大多数简单的使用情况,您可以使用一个小帮手,像这样的:

object DelayedFuture {
  import java.util.{Timer, TimerTask}
  import java.util.Date
  import scala.concurrent._
  import scala.concurrent.duration.FiniteDuration
  import scala.util.Try

  private val timer = new Timer(true)

  private def makeTask[T]( body: => T )( schedule: TimerTask => Unit )(implicit ctx: ExecutionContext): Future[T] = {
    val prom = Promise[T]()
    schedule(
      new TimerTask{
        def run() {
          // IMPORTANT: The timer task just starts the execution on the passed
          // ExecutionContext and is thus almost instantaneous (making it 
          // practical to use a single  Timer - hence a single background thread).
          ctx.execute( 
            new Runnable {
              def run() {
                prom.complete(Try(body))
              }
            }
          )
        }
      }
    )
    prom.future
  }
  def apply[T]( delay: Long )( body: => T )(implicit ctx: ExecutionContext): Future[T] = {
    makeTask( body )( timer.schedule( _, delay ) )
  }
  def apply[T]( date: Date )( body: => T )(implicit ctx: ExecutionContext): Future[T] = {
    makeTask( body )( timer.schedule( _, date ) )
  }
  def apply[T]( delay: FiniteDuration )( body: => T )(implicit ctx: ExecutionContext): Future[T] = {
    makeTask( body )( timer.schedule( _, delay.toMillis ) )
  }
}

这可以像这样使用:

import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits._

DelayedFuture( 5 seconds )( println("Hello") )

需要注意的是与Java计划期货,这个实现不会让你取消的未来。



Answer 4:

如果你想安排不阿卡完成后,您可以使用常规的Java定时器来安排一个承诺来完成:

def delay[T](delay: Long)(block: => T): Future[T] = {
  val promise = Promise[T]()
  val t = new Timer()
  t.schedule(new TimerTask {
    override def run(): Unit = {
      promise.complete(Try(block))
    }
  }, delay)
  promise.future
}


Answer 5:

我的解决方案是非常相似雷吉斯的,但我用阿卡时间表:

 def delayedFuture[T](delay: FiniteDuration)(block: => T)(implicit executor : ExecutionContext): Future[T] = {
    val promise = Promise[T]

    Akka.system.scheduler.scheduleOnce(delay) {
      try {
        val result = block
        promise.complete(Success(result))
      } catch {
        case t: Throwable => promise.failure(t)
      }
    }
    promise.future
  }


Answer 6:

所有其他解决方案,请使用阿卡或阻止每延期任务的线程。 一个更好的解决(除非你已经使用了阿卡)是使用Java的的ScheduledThreadPoolExecutor。 这里有一个斯卡拉包装为的一个例子:

https://gist.github.com/platy/8f0e634c64d9fb54559c



Answer 7:

这个最短的解决方案,可能是利用斯卡拉 - 异步的:

import scala.async.Async.{async, await}

def delay[T](value: T, t: duration): Future[T] = async {
  Thread.sleep(t.toMillis)
  value
}

或者,如果你想有一个块的延迟执行

def delay[T](t: duration)(block: => T): Future[T] async {
  Thread.sleep(t.toMillis)
  block()
}


文章来源: Scala - ScheduledFuture
标签: scala future