【问题标题】:How to add a deadline to a future in Scala?如何在 Scala 中为未来添加截止日期?
【发布时间】:2021-07-06 04:39:15
【问题描述】:

假设我有一个函数fab: A => Future[B] 并希望它返回一个在截止日期之前完成的新未来。所以我正在写一个像这样的新函数deadlined

def deadlined[B](fut: => Future[B], deadline: Deadline): Future[B] = ???

现在我使用java.util.Timer,但可以使用ScheduledThreadPoolExecutor 作为suggested。最好的解决方案可能是一个包装器,用于抽象出调度实现并在测试中将其模拟为 cmets 中的suggested

object Deadlined {

  private val timer = new java.util.Timer() // todo: replace it with a wrapper

  def apply[B](fut: => Future[B], deadline: Deadline)(implicit ec: ExecutionContext): Future[B] = {
    val promise = Promise[B]()
    val timerTask = new java.util.TimerTask {
      override def run(): Unit = promise.failure(new Exception(s"$deadline is exceeded"))
    }
    timer.schedule(timerTask, deadline.timeLeft.toMillis)
    fut.transform { result =>
      timerTask.cancel()
      result match {
        case Success(b) => promise.success(b)
        case Failure(t) => promise.failure(t)
      }
      result
    }
    promise.future
  }
}

这有意义吗?我还想知道如何从对我上一个问题的回复中提取出DeadlinedDelayed 的共同部分。

【问题讨论】:

标签: scala future deadlines


【解决方案1】:

我可能会做类似以下的事情,所以我可以为任何 Future(YMMV、Caveat Emptor 等)添加截止日期:

import scala.concurrent.{Future, ExecutionContext}
import scala.concurrent.duration.FiniteDuration
import java.util.{Timer, TimerTask}

implicit class DeadlineFuture[T](future: Future[T]) {
  def deadline(d: FiniteDuration)(implicit timer: Timer): Future[T] = {
    if (future.isCompleted) future
    else {
      val promise = Promise[T]()
      val timerTask = new TimerTask {
        override def run(): Unit = promise.tryFailure(new Exception(s"$d is exceeded"))
      }
      timer.schedule(timerTask, d.toMillis)
      future.onComplete(_ => timerTask.cancel())(ExecutionContext.parasitic)
      promise.completeWith(future).future
    }
  }
}

// Usage:
Future.never.deadline(5.seconds).onComplete(println)

【讨论】:

  • 谢谢。为什么tryFailure 而不是failure 承诺?
  • 因为如果承诺在未来完成,那么 tmer 任务中的promise.failure(…) 将抛出一个执行。 (取消 TimerTask 和尝试设置失败的 TimerTask 之间存在竞争。
  • 哦,我明白了。谢谢。
  • if (future.isCompleted) future 是优化并且没有它的功能是否正确?
  • 确实,Michael — 在某些情况下,当已知不需要 TimerTask 时,您会希望减少调度 TimerTask 的压力。
猜你喜欢
  • 1970-01-01
  • 2011-09-16
  • 2020-01-26
  • 1970-01-01
  • 1970-01-01
  • 2016-09-02
  • 1970-01-01
  • 2021-11-18
  • 1970-01-01
相关资源
最近更新 更多