There is almost no difference between future { jfuture.get }
and future { future { jfuture.get }}
.
There are as many treads in default thread pool as many you have processors.
With jfuture.get
you'll get 1 thread blocked.
Let's assume you have 8 processors. Also let's suppose each jfuture.get
takes 10 seconds. Now create 8 future { jfuture.get }
.
val format = new java.text.SimpleDateFormat("HH:mm:ss").format(_: Date)
val startTime = new Date
(1 to 8) map {_ => future{ Thread.sleep(10000) }}
future{
2+2
println(s"2+2 done. Start time: ${format(startTime)}, end time: ${format(new Date)}")
}
// 2+2 done. Start time: 20:48:18, end time: 20:48:28
10 seconds is a little too long for 2+2
evaluation.
All other future
s and all actors on the same execution context will be stopped for 10 seconds.
With additional execution context:
object BlockingExecution {
val executor = ExecutionContext.fromExecutor(new ForkJoinPool(20))
}
def blockingFuture[T](f: => T) = {
future( f )(BlockingExecution.executor)
}
val startTime = new Date
(1 to 8) map {_ => blockingFuture{ Thread.sleep(10000) }}
future{
2+2
println(s"2+2 done. Start time: ${format(startTime)}, end time: ${format(new Date)}")
}
// 2+2 done. Start time: 21:26:18, end time: 21:26:18
You could implement blockingFuture
using new Thread(new Runnable {...
, but additional execution context allows you to limit threads count.