【发布时间】:2021-06-21 00:30:36
【问题描述】:
我正在编写一个简单的函数来返回一个在给定延迟后完成的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 的最简单方法是什么?
【问题讨论】:
-
确实有点复杂——说到定时器,有一些重要的因素会影响系统运行时的性能。支持什么精度?支持什么分辨率?计时器的可扩展性如何(即一次可以轻松处理多少个任务)?定时器的生命周期是如何管理的? (即如果计时器关闭,计划的事情不会被执行吗?谁关闭了它?)
-
哇!这是很多问题。不确定我能回答他们...
-
我知道 :) 这也是为什么我还没有为 Scala Futures 添加内置 Timer 工具的原因。这是一个困难的问题空间——一般地解决。
-
确实——将事物变成全局变量会使它们的测试变得极其棘手。一个选项是使实现可实例化以进行测试并在其上执行测试。但这意味着将计时器与使用全局计时器的逻辑分开测试。除非在测试期间使用一些巧妙的技巧来用模拟(反射?)替换全局。
-
不要使用
java.util.Timer。它早已被ScheduledExecutorService取代。您可以创建一个实例,例如通过Executors.newScheduledThreadPool(int)或Executors.newSingleThreadScheduledExecutor()。
标签: scala concurrency timer future