I would like to clear up what it means to be a asynchronous/synchronous and blocking/non-blocking operations in Scala Play using Scala's Future.
So we can have:
Asynchronous and non-blocking
Asynchronous and blocking
Synchronous and non-blocking
Synchronous and blocking
In the Play documentation it says that all operations are asynchronous. But I would like to know how the following would be classed:
If I call an external web service and I have to wait for the response then is this considered to be a asynchronous and blocking operation? For example:
def externalWebCall(url : String): Future[SomeData]
def storeData(data : String) : Future[Unit]
for {
data <- externalWebCall(url)
_ <- storeData(data)
} yield(data)
In this example, I don't want storeData to execute until the externalWebCall service has completed. Is the above code the right way to achieve this? If so I think this is asynchronous and blocking.
The initial request that comes to Play service is treated in an asynchronous and non-blocking way according to the documentation. My understanding of this is that when the Play server receives the request it will not block the main thread. It will then service the request and then make a call to the callback of this request and then return the result. Is that correct?
When people use the term "asynchronous", they usually mean "non-blocking", in the sense that the current execution thread will not stop and wait for the result. In general, synchronous means blocking, asynchronous means non-blocking.
It seems you are confusing "blocking" with "ordering the execution". Your example with the Futures is completely asynchronous, and it equivalent to
val result: Future[Unit] = externalWebCall(url).flatMap(storeData)
storeData can only execute when externalWebCall is done, but any code that would come after val result = ... could also execute before either externalWebCall or storeData. The execution of these methods is wrapped in a Future and run in a different thread, so you have no way of knowing when it will happen. That is what asynchronous means.
The terms blocking and asynchronous have different meanings, but are often confused or used interchangeably.
blocking means that the current thread waits for another thread to do something before executing further instructions. The current thread is blocked until the other thread completes and then it can continue.
asynchronous means that an operation happens on another thread while the current thread continues to execute. The current thread initiates an operation but then continues to execute. When the asynchronous operation completes it notifies the current thread by raising an event or calling some event handler function.
Blocking functions look like normal functions and there is not necessarily any indication that the code being called is blocking or non blocking. So a println statement may be blocking for stderr but non-blocking for stdout.
Asynchronous functions will always have a mechanism for being notified of completion of the operation and this will be visible in the interface. In Scala this usually means returning Future[T] rather than T.
In your example, both externalWebCall and storeData are asynchronous because each method returns Future.
storeData takes a data argument that is only available when externalWebCall completes, so these two operations must by definition operate sequentially.
Related
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
Is using Await wrong? My code doesn't wait for Futures to finish otherwise
If so, What is the alternative?
How do I ensure that the Future and its callback have completed before my main program exits ?
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.
I need Scalaz Task (or some wrapper) which is already running, and can return value immediately if it is completed, or after some waiting if it is not. In terms of Future I could do it like this:
val f = myTask.get.started
This way I have Future running asynchronously, which on f.run returns result immediately when called after the computation is complete, or blocks for some time and waits for completion if it is not. However, this way I loose error handling.
How to have Task and not use Future, but still have it already running asynchronously before run, or runAsync is called on it?
The intention of scalaz.Task is clear control over the execution, which makes referential transparency possible. If you want to fork off the Task, use:
val result = Task.fork(myTask)
and the task will run in its own threadpool as soon as you run it with one of the unsafe* methods.
I have been learning the internals of an operating system and I am confused as to what the basic difference between synchronous and asynchronous I/O is.
How does an operating system know whether it is synchronous or asynchronous?
Synchronous I/O mean that some flow of execution (such as a process or thread) is waiting for the operation to complete. Asynchronous I/O means that nothing is waiting for the operation to complete and the completion of the operation itself causes something to happen.
Synchronous I/O -- some execution vehicle (like a process or thread) that initiates the I/O also waits for the I/O to complete (and perhaps completes it). When the I/O completes, that same execution vehicle goes on to do something else, perhaps using the results of the I/O.
Example:
int i = read (file_handle, buffer, length);
if (i <= 0)
return;
// handle results
Here, the read operation starts a read from the file. The same thread that calls read gets the return value when the read operation completes and can process the result.
Asynchronous I/O -- no execution vehicle waits for the I/O to complete. When the I/O completes, whatever execution vehicle happens to complete the I/O may arrange for later things to happen.
Example:
async_read (file_handle, buffer, length, completion_handler);
// do other stuff having nothing to do with the read
...
completion_handler(int count)
{
if (count < 0)
return;
// handle results
}
Here, the call to async_read starts the read operation. The thread that started the operation can go on to do other things entirely. When the operation completes, the implementation calls completion_handler (possibly by another thread) which gets the results of the operation.
Generally the operating system doesn't have to know which is which. You can, for example, implement only asynchronous operations and have the completion handler unblock the synchronous thread. Usually, deep under the hood, they all look the same with some piece of code called when the operation completes that does whatever has to be done.
You can easily turn either into the other.
If you have only asynchronous operations and want a synchronous operation, just call the asynchronous operation and then block on something that is unblocked by the completion handler.
If you have only synchronous operations and want an asynchronous operation, just create a new thread to call the synchronous operation and have it invoke the completion handler when the synchronous operation returns.
So I'm writing a mini timeout library in scala, it looks very similar to the code here: How do I get hold of exceptions thrown in a Scala Future?
The function I execute is either going to complete successfully, or block forever, so I need to make sure that on a timeout the executing thread is cancelled.
Thus my question is: On a timeout, does awaitAll terminate the underlying actor, or just let it keep running forever?
One alternative that I'm considering is to use the java Future library to do this as there is an explicit cancel() method one can call.
[Disclaimer - I'm new to Scala actors myself]
As I read it, scala.actors.Futures.awaitAll waits until the list of futures are all resolved OR until the timeout. It will not Future.cancel, Thread.interrupt, or otherwise attempt to terminate a Future; you get to come back later and wait some more.
The Future.cancel may be suitable, however be aware that your code may need to participate in effecting the cancel operation - it doesn't necessarily come for free. Future.cancel cancels a task that is scheduled, but not yet started. It interrupts a running thread [setting a flag that can be checked]... which may or may not acknowledge the interrupt. Review Thread.interrupt and Thread.isInterrupted(). Your long-running task would normally check to see if it's being interrupted (your code), and self-terminate. Various methods (i.e. Thread.sleep, Object.wait and others) respond to the interrupt by throwing InterruptedException. You need to review & understand that mechanism to ensure your code will meet your needs within those constraints. See this.
Futures are very convenient, but in practice, you may need some guarantees on their execution. For example, consider:
import scala.actors.Futures._
def slowFn(time:Int) = {
Thread.sleep(time * 1000)
println("%d second fn done".format(time))
}
val fs = List( future(slowFn(2)), future(slowFn(10)) )
awaitAll(5000, fs:_*)
println("5 second expiration. Continuing.")
Thread.sleep(12000) // ie more calculations
println("done with everything")
The idea is to kick off some slow running functions in parallel. But we wouldn't want to hang forever if the functions executed by the futures don't return. So we use awaitAll() to put a timeout on the futures. But if you run the code, you see that the 5 second timer expires, but the 10 second future continues to run and returns later. The timeout doesn't kill the future; it just limits the join wait.
So how do you kill a future after a timeout period? It seems like futures can't be used in practice unless you're certain that they will return in a known amount of time. Otherwise, you run the risk of losing threads in the thread pool to non-terminating futures until there are none left.
So the questions are: How do you kill futures? What are the intended usage patterns for futures given these risks?
Futures are intended to be used in settings where you do need to wait for the computation to complete, no matter what. That's why they are described as being used for slow running functions. You want that function's result, but you have other stuff you can be doing meanwhile. In fact, you might have many futures, all independent of each other that you may want to run in parallel, while you wait until all complete.
The timer just provides a wait to get partial results.
I think the reason Future can't simply be "killed" is exactly the same as why java.lang.Thread.stop() is deprecated.
While Future is running, a Thread is required. In order to stop a Future without calling stop() on the executing Thread, application specific logic is needed: checking for an application specific flag or the interrupted status of the executing Thread periodically is one way to do it.