【问题标题】:Future Not Completed But Looks Like it Has未来尚未完成,但看起来已经完成
【发布时间】:2018-11-08 19:28:25
【问题描述】:

我是一个试图理解 Futures 的 Scala 新手。我在 REPL 中输入了以下内容:

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

scala> import scala.concurrent.Future
import scala.concurrent.Future

scala> val m = Future(println("Message"))
Message
m: scala.concurrent.Future[Unit] = Future(<not completed>)

scala> Future(println("Another Message"))
res4: scala.concurrent.Future[Unit] = Future(<not completed>)
Another Message

在第一种情况下,我将 Future 计算分配给变量 m。我还没有打电话给m,但Future 实际上会产生“消息”字符串输出。但我也收到了Future(&lt;not completed&gt;) 消息。这里发生了什么?未来是否已经完成?字符串输出告诉我它有。有人可以帮我解决这个问题吗?

【问题讨论】:

    标签: scala


    【解决方案1】:

    Future 将在创建后立即开始执行(取决于 ExecutionContext 实现并假设有资源可供其运行。)

    您看到打印到控制台的消息表明您的 Futures 已完成。

    尝试以下操作,看看会发生什么:

    Future{
      Thread.sleep(5000)
      println("Message")
    }
    

    【讨论】:

    • 这有点奇怪,它在创建后开始执行,而我什至没有调用它。当我在上面的示例中调用 m 时,我本来希望它开始执行。
    • 这个链接解释了幕后发生的事情:beyondthelines.net/computing/scala-future-and-execution-context
    • @Mojo m 不是 lazydef。它会在定义时被计算。如果您希望它在计算之前等到它被调用,请将其弹出一个函数或使 val 变得惰性。
    • @Mojo 是的,任何vals 都一样。如果它们不是惰性的(或未定义为def m = ....),它们将在定义时被读入内存。制作一个 val lazy 基本上是告诉编译器在稍后使用它之前不要担心计算它的值 - 就编译器而言,它可能是一个注释或新行(一旦它发现因为 val 是惰性的)。
    • 尽管正如@TerryDactyl 指出的那样,不同的 ExecutionContext 运行方式不同,因此这不是通用规则。不过,就scala.concurrent.ExecutionContext.Implicits.global 而言,您可以假设它是正确的。
    【解决方案2】:

    完成了,你看到的Future(&lt;not completed&gt;) 只是来自Future 的`toString()。

    尝试:

    import scala.concurrent.ExecutionContext.Implicits.global
    
    val f = scala.concurrent.Future{
      println("Message")
    }
    
    println(f.toString())
    

    未来总是急切地执行。

    【讨论】:

      猜你喜欢
      • 2021-05-05
      • 1970-01-01
      • 1970-01-01
      • 2014-10-13
      • 2019-08-12
      • 2023-03-03
      • 2015-01-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多