Scala - ScheduledFuture
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16359849/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Scala - ScheduledFuture
提问by Bober02
I am trying to implement scheduled future in Scala. I would like it to wait specific time and then execute the body. So far I tried the following, simple approach
我正在尝试在 Scala 中实现预定的未来。我希望它等待特定时间然后执行主体。到目前为止,我尝试了以下简单的方法
val d = 5.seconds.fromNow
val f = future {Await.ready(Promise().future, d.timeLeft); 1}
val res = Await.result(f, Duration.Inf)
but I am getting the TimeoutExcpetion on the future. Is this even the correct approach or should I simply use the ScheduledExecutor from Java?
但我在未来得到了 TimeoutExcpetion。这甚至是正确的方法还是我应该简单地使用 Java 中的 ScheduledExecutor?
采纳答案by cmbaxter
You could change your code to something like this:
您可以将代码更改为如下所示:
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))
}
But I would not recommend it. In doing so, you would be blocking in a Future (blocking to wait for that Promisethat will never complete), and I think blocking in the ExecutionContextis greatly discouraged. I would either look into using the java scheduled executor as you stated or you could look into using Akka as @alex23 recommended.
但我不会推荐它。这样做时,您将阻塞在 Future 中(阻塞以等待Promise永远不会完成的),我认为ExecutionContext非常不鼓励阻塞。我要么像你说的那样考虑使用 java 计划执行器,要么你可以像@alex23 推荐的那样考虑使用 Akka。
回答by Viktor Klang
Akka has akka.pattern:
Akka 有 akka.pattern:
def after[T](duration: FiniteDuration, using: Scheduler)(value: ? Future[T])(implicit ec: ExecutionContext): Future[T]
"Returns a scala.concurrent.Future that will be completed with the success or failure of the provided value after the specified duration."
“返回一个 scala.concurrent.Future,它将在指定的持续时间后以提供的值的成功或失败来完成。”
回答by Régis Jean-Gilles
There is nothing to do that out of the box using the standard library alone. For most simple use cases, you can use a little helper such as this:
单独使用标准库没有什么可以开箱即用的。对于大多数简单的用例,您可以使用一个小助手,例如:
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 ) )
}
}
This can be used like this:
这可以像这样使用:
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits._
DelayedFuture( 5 seconds )( println("Hello") )
Note that unlike java scheduled futures, this implementation will not let you cancel the future.
请注意,与 java 预定期货不同,此实现不会让您取消期货。
回答by Arne Claassen
If you want schedule the completion without Akka, you can use a regular Java Timer to schedule a promise to complete:
如果你想在没有 Akka 的情况下安排完成,你可以使用一个常规的 Java Timer 来安排一个承诺完成:
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
}
回答by agabor
My solution is pretty similar to Régis's but I use Akka to schedule:
我的解决方案与 Régis 的解决方案非常相似,但我使用 Akka 来安排:
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
}
回答by MikeB
All the other solutions use either akka or block a thread per delayed task. A better solution (unless you are already using akka) is to use java's ScheduledThreadPoolExecutor. Here's an example of a scala wrapper for that:
所有其他解决方案使用 akka 或为每个延迟任务阻塞一个线程。更好的解决方案(除非您已经在使用 akka)是使用 java 的 ScheduledThreadPoolExecutor。这是一个 Scala 包装器的例子:
回答by pjan
Shortest solution for this, is probably making use of scala-async:
对此的最短解决方案,可能是使用 scala-async:
import scala.async.Async.{async, await}
def delay[T](value: T, t: duration): Future[T] = async {
Thread.sleep(t.toMillis)
value
}
Or in case you want delayed execution of a block
或者如果你想延迟执行一个块
def delay[T](t: duration)(block: => T): Future[T] async {
Thread.sleep(t.toMillis)
block()
}

