Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I block on a Future - scala

Tags:

scala

According to Scala documentation, no blocking should be done on Future.

"As mentioned earlier, blocking on a future is strongly discouraged for the sake of performance and for the prevention of deadlocks. Callbacks and combinators on futures are a preferred way to use their results. However, blocking may be necessary in certain situations and is supported by the Futures and Promises API."

How can I ensure that my all the Futures have completed (and their callbacks finished) before my program exits? I usually use Await.result at the end of my main function to ensure that all Futures have completed.

object ConcurrencyExample extends App {
val gpf= Future {some operations}
val ccf = Future{some operations}


val atbf = for {g <- gpf
c <- ccf if c == true}  yield {some operations}

//is it OK to use Await? If not, how do I ensure that all Futures have finished
        ?
Await.result(atbf,1000 millis )
 }

Questions

  1. Is using Await wrong? My code doesn't wait for Futures to finish otherwise
  2. If so, What is the alternative?
  3. How do I ensure that the Future and its callback have completed before my main program exits ?
like image 640
Manu Chadha Avatar asked Jan 04 '23 20:01

Manu Chadha


1 Answers

Yes you can Await.result in your case.

You can use Await.result for keeping main thread alive for futures to complete

Becareful with Await.result

Note this applies for both Akka and play apps

Await.result should be used very carefully only when it is absolutely necessary.

Await.result blocks the thread in which it is running until the given duration. Blocking the thread will waste the precious computation resource because that thread will not be able to do any useful computation like handling the new request or number crunching in an algorithm etc.

So, Avoid using the Await.result as much as possible.

But, when do we use it (Await.result) ?

Here is one of the typical use case for using Await.result.

Lets say you have written a program containing main thread and all the computation inside the main thread is asynchronous. Now once you start the asynchronous computation inside the main thread. Some one has to stop the main thread from existing till the asynchronous computation finishes, if not the program stops running and you cannot see the result of the asynchronous computation.

When an application begins running, there is one non-daemon thread, whose job is to execute main(). JVM will not exit by itself until and unless non-daemon threads are completed.

object Main {
 def main(args: Array[String]): Unit = {
  import scala.concurrent.Future
  import scala.concurrent.duration._

  val f = Future { //do something }
  //stop main thread till f completes
  Await.result(f, 10 seconds)
 }
}

Future uses daemon threads for running. So daemon threads cannot stop the JVM from shutting down. So JVM shuts down even if non-daemon threads are running.

In the above case there is no other way expect stopping (blocking) the main thread till the computation f completes if not main thread exits and computation stops.

In most of the cases you do not need to use Await.result and simple Future composition using map and flatMap would suffice.

Risks of using Await.result (In general all blocking code)

Running out of threads in event based model

In event based model you will quickly run out of threads if you have blocking code which takes long time to return. In playframework any blocking call could decrease the performance of the application and app will becomes dead slow as it runs out of threads.

Running out of memory in non-event based models

In thread per request models. When you have blocking calls which take long time to exit/return.

case 1: If you have fixed thread pool then application might run out of threads.

case 2: If you have dynamically growing thread pool then your application will suffer from too much context switching overhead and also will run out of memory because of too many blocked threads in memory.

In all of the cases no useful work is done expect for waiting for some IO or some other event.

like image 102
pamu Avatar answered Jan 11 '23 16:01

pamu