为什么我的简单 Scala 对象在包含未来时会挂起一分钟左右
Why does my simple scala object hangs for a minute or so while it includes a future
我正在学习 scala futures,我已经回答了我的问题。我有一个很简单的例子
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._
import scala.util.{Failure, Success}
/**
* Created by dummy on 05/02/15.
*/
object FutureUtils extends App{
val f = Future {
Thread.sleep(1000)
println("I am learning scala futures")
"learning"
}
f onComplete {
case Success(value:String) => println("got the response back")
case Failure(t: Throwable) => println("did not expect this")
}
println("I am still learning")
}
当我 运行 程序按原样输出时从不打印
got the response back
相反,它看起来像是挂起一分钟左右,并且没有打印出预期的输出就结束了。我确定我在这里遗漏了一些非常基本的东西。
我也尝试在末尾添加 System.in.read()
,似乎当我输入任何虚拟值时,程序结束打印预期结果。这种行为背后的原因是什么?谁能帮我理解一下?
没有 System.in.read()
程序无法运行的原因是 onComplete
在 future 完成之前不会阻塞,而只是在它完成时添加一个回调。该回调永远不会被执行,因为整个程序在 future 完成之前就结束了。要解决此问题,您可以故意让主线程进入无限循环并在回调中显式终止进程。
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._
import scala.util.{Failure, Success}
object Main extends App {
val f = Future {
Thread.sleep(1000)
println("I am learning scala futures")
"learning"
}
f onComplete {
case Success(value:String) => println("got the response back"); System.exit(0)
case Failure(t: Throwable) => println("did not expect this"); System.exit(1)
}
println("I am still learning")
while (true){
Thread.sleep(1000)
}
}
嗯...因为你在你的未来中睡了 1000 毫秒,你的未来至少需要 1 秒才能完成。应用线程在此时完成并退出。
您必须确保应用程序线程在 future 完成时处于活动状态。您可以通过在您的应用程序线程中休眠一段时间来做到这一点……就像这样。
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._
import scala.util.{Failure, Success}
object FutureUtils extends App{
val f = Future {
Thread.sleep(1000)
println("I am learning scala futures")
"learning"
}
f onComplete {
case Success(value:String) => println("got the response back")
case Failure(t: Throwable) => println("did not expect this")
}
// Wait for some time
// Not sure future will complete in this time or not
Thread.sleep(1000);
Thread.sleep(1000);
Thread.sleep(1000);
}
但是,更好的方法是让应用程序线程需要 future 才能完成。
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._
import scala.util.{ Failure, Success }
object FutureUtils extends App {
val f = Future {
Thread.sleep( 1000 )
println( "I am learning scala futures" )
"learning"
}
f onComplete {
case Success( value:String ) => println( "got the response back" )
case Failure( t: Throwable ) => println( "did not expect this" )
}
while ( f.value == None ) {
// Waste time just till the future is complete.
}
// Do something with future value.
f.foreach( ( s: String ) => println( s ) )
}
您需要等待未来,程序在完成之前正在退出。
import scala.concurrent.Await
import scala.concurrent.duration._
var myFuture = Future {
Thread.sleep(1000)
1
}
// oncomplete handlers, etc here
println(Await.result(myFuture, 5 seconds))
编辑:如果您必须使用 onComplete
并且无法验证这些处理程序是否在 Await.ready/result
之前执行,那么您应该使用正式同步,即:
import scala.concurrent._
import java.util.concurrent.CountDownLatch
object Main extends App {
val f = Future {
Main.synchronized {
Thread.sleep(1000);
1
}
}
val latch = new CountDownLatch(1)
f.onComplete {
case _ => { latch.countDown() }
}
latch.await()
}
我正在学习 scala futures,我已经回答了我的问题。我有一个很简单的例子
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._
import scala.util.{Failure, Success}
/**
* Created by dummy on 05/02/15.
*/
object FutureUtils extends App{
val f = Future {
Thread.sleep(1000)
println("I am learning scala futures")
"learning"
}
f onComplete {
case Success(value:String) => println("got the response back")
case Failure(t: Throwable) => println("did not expect this")
}
println("I am still learning")
}
当我 运行 程序按原样输出时从不打印
got the response back
相反,它看起来像是挂起一分钟左右,并且没有打印出预期的输出就结束了。我确定我在这里遗漏了一些非常基本的东西。
我也尝试在末尾添加 System.in.read()
,似乎当我输入任何虚拟值时,程序结束打印预期结果。这种行为背后的原因是什么?谁能帮我理解一下?
没有 System.in.read()
程序无法运行的原因是 onComplete
在 future 完成之前不会阻塞,而只是在它完成时添加一个回调。该回调永远不会被执行,因为整个程序在 future 完成之前就结束了。要解决此问题,您可以故意让主线程进入无限循环并在回调中显式终止进程。
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._
import scala.util.{Failure, Success}
object Main extends App {
val f = Future {
Thread.sleep(1000)
println("I am learning scala futures")
"learning"
}
f onComplete {
case Success(value:String) => println("got the response back"); System.exit(0)
case Failure(t: Throwable) => println("did not expect this"); System.exit(1)
}
println("I am still learning")
while (true){
Thread.sleep(1000)
}
}
嗯...因为你在你的未来中睡了 1000 毫秒,你的未来至少需要 1 秒才能完成。应用线程在此时完成并退出。
您必须确保应用程序线程在 future 完成时处于活动状态。您可以通过在您的应用程序线程中休眠一段时间来做到这一点……就像这样。
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._
import scala.util.{Failure, Success}
object FutureUtils extends App{
val f = Future {
Thread.sleep(1000)
println("I am learning scala futures")
"learning"
}
f onComplete {
case Success(value:String) => println("got the response back")
case Failure(t: Throwable) => println("did not expect this")
}
// Wait for some time
// Not sure future will complete in this time or not
Thread.sleep(1000);
Thread.sleep(1000);
Thread.sleep(1000);
}
但是,更好的方法是让应用程序线程需要 future 才能完成。
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._
import scala.util.{ Failure, Success }
object FutureUtils extends App {
val f = Future {
Thread.sleep( 1000 )
println( "I am learning scala futures" )
"learning"
}
f onComplete {
case Success( value:String ) => println( "got the response back" )
case Failure( t: Throwable ) => println( "did not expect this" )
}
while ( f.value == None ) {
// Waste time just till the future is complete.
}
// Do something with future value.
f.foreach( ( s: String ) => println( s ) )
}
您需要等待未来,程序在完成之前正在退出。
import scala.concurrent.Await
import scala.concurrent.duration._
var myFuture = Future {
Thread.sleep(1000)
1
}
// oncomplete handlers, etc here
println(Await.result(myFuture, 5 seconds))
编辑:如果您必须使用 onComplete
并且无法验证这些处理程序是否在 Await.ready/result
之前执行,那么您应该使用正式同步,即:
import scala.concurrent._
import java.util.concurrent.CountDownLatch
object Main extends App {
val f = Future {
Main.synchronized {
Thread.sleep(1000);
1
}
}
val latch = new CountDownLatch(1)
f.onComplete {
case _ => { latch.countDown() }
}
latch.await()
}