【问题标题】:Why does `Future#toString` returns `"List()"`?为什么`Future#toString` 返回`"List()"`?
【发布时间】:2016-07-21 02:48:33
【问题描述】:

在没有等待完成的情况下就未来调用.toString 会导致不确定的结果。我的问题是为什么在 scala 2.10.x 和 2.11.x 中调用 .toString 未完成的期货返回 "List()"? The implementation 似乎并没有明确说明这一点。

可以从 REPL 中观察到这种行为:

scala> import scala.concurrent.Future, scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.ExecutionContext.Implicits.global

scala> Future(1).toString
res0: scala.concurrent.Future[Int] = Success(1)

scala> Future(1).toString
res1: scala.concurrent.Future[Int] = List()

请注意,Scala 2.12.x 可能会显式实现 Future#toString 以返回 "Future(<not completed>)" (source)。


编辑:证明这不是来自 REPL 的人工制品或“一些隐藏的隐含”(-Yno-predef 删除了所有默认隐含):

Future.scala:

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

object Main extends App {
  System.out.println(Future(1).toString)
}

build.sbt:

scalaVersion := "2.11.8"

scalacOptions := Seq(
  "-deprecation",
  "-encoding", "UTF-8",
  "-feature",
  "-unchecked",
  "-Yno-predef",
  "-Xfatal-warnings",
  "-Xlint",
  "-Yinline-warnings",
  "-Yno-adapted-args",
  "-Ywarn-dead-code",
  "-Ywarn-unused-import",
  "-Ywarn-numeric-widen",
  "-Ywarn-value-discard",
  "-Xfuture")

【问题讨论】:

  • 我一直在使用 Scala 2.11.7 获得 scala.concurrent.impl.Promise$DefaultPromise@34a2d6e0
  • 在 2.11.8 中,对于未完成的 Future,您确实会得到 List()。
  • 你很可能有一些隐藏的隐式定义会产生这种行为。
  • 这是REPL调试中的一个。尝试将其分配给val
  • @cchantep 我不这么认为,println(Future(1).toString) 也会打印出List(),同样的结果也可以从 REPL 中复制出来。

标签: scala future


【解决方案1】:

这是删除sun.misc.Unsafe 的依赖的一个不幸的副作用。它在 Scala 2.12 和更新版本的 Scala 2.11 IIRC 中得到纠正。

【讨论】:

  • 确认修复即将在 2.11.9 发布。
  • 出于好奇,您能在这里解释一下sun.misc.Unsafe 与"List()" 的关系吗?
  • 我们通过扩展 AtomicReference 替换了它,遗憾的是它默默地“覆盖”了 toString。正在打印的 List 是回调列表。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-09
相关资源
最近更新 更多