我正在阅读akkaScala文档,有一个例子(第171页)
// imports added for compilation
import scala.concurrent.{ExecutionContext, Future}
import ExecutionContext.Implicits.global
class Some {
}
object Some {
def main(args: Array[String]) {
// Create a sequence of Futures
val futures = for (i <- 1 to 1000) yield Future(i * 2)
val futureSum = Future.fold(futures)(0)(_ + _)
futureSum foreach println
}
}
我跑了,但什么都没发生。我的意思是控制台输出没有任何东西。有什么问题?
答案 0 :(得分:4)
您不会等待将来完成,因此您在退出程序和完成期货以及副作用运行之间创建竞赛。在你的机器上,未来似乎在竞争者中失去了竞争对手。谁说&#34;它的作用&#34;,未来正在赢得比赛。
您可以使用Await阻止未来并等待它完成。这是你应该只做的事情&#34;在世界末日&#34;,你应该很少真正使用Await ......
// imports added for compilation
import scala.concurrent.{ExecutionContext, Future}
import ExecutionContext.Implicits.global
import scala.concurrent.duration._ // for the "1 second" syntax
import scala.concurrent.Await
class Some {
}
object Some {
def main(args: Array[String]) {
// Create a sequence of Futures
val futures = for (i <- 1 to 1000) yield Future(i * 2)
val futureSum = Future.fold(futures)(0)(_ + _)
// we map instead of foreach, to make sure that the side-effect is part of the future
// and we "await" for the future to complete (for 1 second)
Await.result(futureSum map println, 1 second)
}
}
答案 1 :(得分:1)
正如其他人所说,问题是竞争条件,即期货与计划终止竞争。 JVM具有守护程序线程的概念。它等待非守护程序线程终止但不等待守护程序线程。因此,如果您想等待线程完成,请使用非守护程序线程。
为scala future创建线程的方式是使用隐式scala.concurrent.ExecutionContext
。您使用的那个(import ExecutionContext.Implicits.global
)启动守护程序线程。但是,可以使用非守护程序线程。因此,如果您使用带有非守护程序线程的ExecutionContext,它将等待,在您的情况下,这是合理的行为。天真地:
import scala.concurrent.Future
import scala.concurrent.ExecutionContextExecutor
import scala.concurrent.ExecutionContext
class MyExecutionContext extends ExecutionContext {
override def execute(runnable:Runnable) = {
val t = new Thread(runnable)
t.setDaemon(false)
t.start()
}
override def reportFailure(t:Throwable) = t.printStackTrace
}
object Some {
implicit lazy val context: ExecutionContext = new MyExecutionContext
def main(args: Array[String]) {
// Create a sequence of Futures
val futures = for (i <- 1 to 1000) yield Future(i * 2)
val futureSum = Future.fold(futures)(0)(_ + _)
futureSum foreach println
}
}
在生产中使用上述ExecutionContext时要小心,因为它没有使用线程池并且可以创建无界线程,但消息是:您可以通过ExecutionContext控制Futures背后的线程的所有内容。探索各种scala和akka语境,找到你需要的东西,或者如果没有什么适合的话,你可以自己编写。
答案 2 :(得分:0)
主要功能结束时的以下两个陈述都有助于您的需要。正如上面的答案所说,允许未来完成。主线程与Future线程不同,主要完成后,它会在Future thread之前终止。
Thread.sleep(500)// ...简单解决方案
Await.result(futureSum,Duration(500,MILLISECONDS))//...导入scala.concurrent.duration._以使用Duration对象。