我想在斯卡拉实施计划的未来。 我想它等待特定的时间,然后执行体。 到目前为止,我试过以下,简单的方法
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?
你可以更改您的代码是这样的:
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建议。
阿卡有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
没有什么可以做出来单独使用标准库的开箱。 对于大多数简单的使用情况,您可以使用一个小帮手,像这样的:
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计划期货,这个实现不会让你取消的未来。
如果你想安排不阿卡完成后,您可以使用常规的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
}
我的解决方案是非常相似雷吉斯的,但我用阿卡时间表:
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
}
所有其他解决方案,请使用阿卡或阻止每延期任务的线程。 一个更好的解决(除非你已经使用了阿卡)是使用Java的的ScheduledThreadPoolExecutor。 这里有一个斯卡拉包装为的一个例子:
https://gist.github.com/platy/8f0e634c64d9fb54559c
这个最短的解决方案,可能是利用斯卡拉 - 异步的:
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()
}