Scala 未来超时奇怪的行为

scala future timeout strange behaviour

这里是示例代码 scala 2.13.3:

import scala.concurrent.{ExecutionContext}

val scheduller: ScheduledExecutorService = Executors.newSingleThreadScheduledExecutor()

val promise = Promise[A]()
scheduller.schedule(
  new Runnable {
    override def run(): Unit = {
      promise.failure(new TimeoutException)
      scheduller.shutdown()
    }
  },
  500,
  TimeUnit.MILLISECONDS
)
Future.firstCompletedOf(Seq(INF_FUTURE, promise.future))

如果 INF_FUTURE = Future.never 超时将起作用,但如果 INF_FUTURE = Future {while (true) {}} 则执行不会停止 你能解释一下这是怎么回事吗?

因为你使用了singleThreadScheduledExecutor。我假设您从 scheduller:

创建了 ExecutionContext
val scheduller: ScheduledExecutorService = Executors.newSingleThreadScheduledExecutor()
implicit val ec: ExecutionContextExecutor = scala.concurrent.ExecutionContext.fromExecutorService(scheduller)

val promise = Promise[Int]()
scheduller.schedule(
  new Runnable {
    override def run(): Unit = {
      promise.failure(new TimeoutException)
      scheduller.shutdown()
    }
  },
  500,
  TimeUnit.MILLISECONDS
)

如果您只使用一个执行程序创建执行上下文,您的程序将评估同步并冻结在 while (true) 循环中。

如果你切换到全局执行上下文,问题将被遗漏(如果你的机器有一个以上的核心):

implicit val ec: ExecutionContextExecutor = scala.concurrent.ExecutionContext.global

Future.never 的情况下,如果您将像这样等待结果:

Await.result(Future.firstCompletedOf(Seq(INF_FUTURE, promise.future)).map {
  x =>
    println(x)
}, 10.seconds)

你会得到异常:

Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask@eb88a9df rejected from java.util.concurrent.ScheduledThreadPoolExecutor@e24c7ced[Shutting down, pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 1]

这给你打电话是关于线程池大小的问题。 所以,你对 Future.never 没有任何问题,因为你没有等待它的结果。