Say I have a future defined as follows
val fut = Future {
println("Doing some work")
Thread.sleep(5000)
println("Work done")
}
I am accessing this future later in time but would like to have it execute on startup rather than when I reference fut
I read somewhere that it can be executed immediately by doing:
scala.concurrent.ExecutionContext.Implicits.global.execute(fut)
However this will not compile as execute only takes a Runnable. Is there a way I can execute this future immediately in a different thread?
Scala Future
s created using Future.apply
are eagerly executed.
For non-eager execution, you will have to define your own class to indirectly create Future
using Promise
.
import scala.concurrent.{Future, Promise}
import scala.util.{Failure, Success, Try}
class NonEagerFuture[A](computation: => A) extends Runnable {
private val promise = Promise[A]
override def run(): Unit = {
Try(computation) match {
case Success(result) => promise.success(result)
case Failure(exception) => promise.failure(exception)
}
}
def isFutureCompleted(): Boolean =
promise.isCompleted
def getResult(): A =
if (!promise.isCompleted) {
throw new IllegalStateException("Future is not completed yet")
} else {
promise.future.value.get.get
}
def getScalaFuture(): Future[A] =
promise.future
}
It can be used as following,
println("creating the future")
val nonEagerFuture = new NonEagerFuture({
println("Doing some work")
Thread.sleep(5000)
println("Work done")
println("returning 5 as result")
5
})
println("running for the future")
scala.concurrent.ExecutionContext.Implicits.global.execute(nonEagerFuture)
// can also get the internal scala future and use it
// this scala future will not have the eager problem
println("get the scala future")
val scalaFuture = nonEagerFuture.getScalaFuture()
println("printing scalaFuture" + scalaFuture)
// or block for completion using isFutureCompleted
println("checking for the future")
while (!nonEagerFuture.isFutureCompleted()) {
Thread.sleep(1000)
println("Checking completed: " + nonEagerFuture.isFutureCompleted())
}
println("getting result for the future")
println("Result: " + nonEagerFuture.getResult())