Futures do not run before program termination

不羁的心 提交于 2019-11-27 15:09:47

The issue is that you're executing that as a standalone program, whose main thread is terminating before one of the worker threads can execute the "Hello future!" println. (The threads that the new futures library spawns are daemon threads).

You can also use the Await object (also in scala.concurrent) to wait until the future f is completed:

import scala.concurrent._
import scala.concurrent.util._

object Test {
  def main(args: Array[String]) {
    println("Test print before future")

    val s = "Hello"
    val f = future {s + " future!"}
    f onSuccess {case v => println(v)}
    println("Test print after future")

    Await.ready(f, Duration.Inf)
  }
}

This can print:

Test print before future
Test print after future
Hello future!

Or, it can print "Hello future!" before "Test print after future" depending on the thread schedule.

Likewise, you can force the main thread to wait until f is completed before the last println as follows:

import scala.concurrent._
import scala.concurrent.util._

object Test {
  def main(args: Array[String]) {
    println("Test print before future")

    val s = "Hello"
    val f = future {s + " future!"}
    f onSuccess {case v => println(v)}

    Await.ready(f, Duration.Inf)        

    println("Test print after future")
  }
}

Which would print:

Test print before future
Hello future!
Test print after future

However, note that when you use Await, you're blocking. This of course makes sense to make sure that your main application thread doesn't terminate, but generally shouldn't be used unless necessary otherwise.

(The Await object is a necessary escape hatch for situations like these, but using it throughout application code without concern for its semantics can result in slower, less-parallel execution. If you need to ensure that callbacks are executed in some specified order, for example, there are other alternatives, such as the andThen and map methods on Future.)

I think that problem here is timing. Most probably your future code is running in separate deamon thread. I think that application finishes very fast and this deamon thread do not have enough time to execute properly (application does not wait for deamon threads to finish). But this also very system-dependent behavior. For me it prints:

Test print before future
Test print after future
Hello future!

and then exits (I'm using Scala 2.10.0-M3). You can try following in order to test it - just put main execution thread in sleep for several seconds and see whether Hello future! is printed:

import scala.concurrent.Future
import scala.concurrent.future

object Test {
    def main(args: Array[String]) {
        println("Test print before future")

        val s = "Hello"
        val f = future {s + " future!"}
        f onSuccess {case v => println(v)}

        println("Test print after future")

        Thread.sleep(3000) 
        println("Test print at the end.")
    }
}
bluenote10

I just want to add that in general there is another possibility that futures are not running: Hitting the thread pool limit.

In your case it probably was simply a timing issue as others have pointed out, but as future reference consider this example:

import scala.concurrent._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.Duration


object FutureDebug {
  def main( args: Array[String] ) {

    for (i <- Range(0, 4)) {
      future {
        while (true) {
          Thread.sleep(1000)
          println("I'm doing stupid things in a future")
        }
      }
    }

    println("(1) reached? yes")
    val fut = future {
      for (i <- Range(0, 1000)) {
        println("never reached " + i)
      }
      3.14
    }    
    println("(2) reached? yes")
    Await.result(fut, Duration.Inf)
    println("(3) reached? no")
  }
}

On my machine the default global execution context has just 4 Threads. Since the worker threads are busy executing the 4 non-sense futures, the future below will never run. This is why one should be careful with the default execution context and it is best to specify one's own execution context when dealing with multiple (really) long running futures.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!