没有java.util.Timer如何实现延迟的未来?

How to implement a delayed future without java.util.Timer?

我正在为 return 编写一个简单的函数,一个 Future[Unit] 在给定的延迟后完成。

def delayedFuture(delay: FiniteDuration): Future[Unit] = {
  val promise = Promise[Unit]()
  val timerTask = new java.util.TimerTask {
    override def run(): Unit = promise.complete(Success(()))
  }
  new java.util.Timer().schedule(timerTask, delay.toMillis)
  promise.future
}

此实现可能可行,但我不喜欢为每次调用创建一个新的 Timer,因为每个 Timer 实例都会创建一个线程。我可以将 Timer 实例作为参数传递给 delayedFuture,但我不想让客户端代码知道 Timer。所以我想我根本不能使用 java.util.Timer

我想使用 ExecutionContext 进行任务调度,也许可以这样定义 delayedFuture

def delayedFuture(delay: FiniteDuration)
                 (implicit ec: ExecutoionContext): Future[Unit] = ???

在没有 java.util.Timer 的情况下实现 delayedFuture 的最简单方法是什么?

您可以使用 Java 的 ScheduledExecutorService 之一,例如创建一个单线程池并将其仅用于调度:

val svc = new ScheduledThreadPoolExecutor(1, (r: Runnable) => {
    val t = new Thread(r)
    t.setName("future-delayer")
    t.setDaemon(true) // don't hog the app with this thread existing
    t
})

def delayedFuture(d: FiniteDuration) = {
  val p = Promise[Unit]()
  svc.schedule(() => p.success(()), d.length, d.unit)
  p.future
}

您无需为每次调用创建新的 Timer。只做一个全球的。

object Delayed {
  private val timer = new Timer
  def apply[T](delay: Duration)(task: => T): Future[T] = {
    val promise = Promise[T]()
    val tt = new TimerTask {
      override def run(): Unit = promise.success(task)
    }
    timer.schedule(tt, delay.toMillis)
    promise.future
  }

  def unit(delay: Duration) = apply[Unit](delay) { () }
}

然后,Delayed.unit(10 seconds) 给你一个在 10 秒内满足的未来单位。