I've read a few tutorials on how to deal with concurrency in Play and found some examples:
Asynchronous Job
import scala.concurrent.{ExecutionContext, future}
def sendEmailAsync(from: String, to: String, subject: String, body: String) = {
import ExecutionContext.Implicits.global // in scala.concurrent
future {
EmailHelper.sendEmail(from, to, subject, body)
}
}
Scheduled Job
import play.api.libs.concurrent.{Akka, Execution}
def sendEmailOnSchedule(from: String, to: String, subject: String, body: String) = {
import scala.concurrent.duration._
import Execution.Implicits.defaultContext // in play.api.libs.concurrent
Akka.system.scheduler.scheduleOnce(10 seconds) {
EmailHelper.sendEmail(from, to, subject, body)
}
}
Well, I'm a bit confused... the first example uses scala.concurrent.ExecutionContext.Implicits.global while the second example uses play.api.libs.concurrent.Execution.Implicits.defaultContext. Why? Could someone explain me what is going on behind the scene?
Scala uses an
ExecutionContextfor some asynchronous things (Futures, Promises). An ExecutionContext can be thought of like a Thread Pool, in whichRunnablescan be submitted to be run on one of the threads. (It isn't necessarily always a thread pool, but it tends to be).The way the ExecutionContext is used is usually to pass it in as an
implicitargument to the function that would use it. You'll often see method signatures like this:The "doAsyncThings" method will use the implicit
excthat gets passed in to put work onto a separate thread.To answer your question, the
Implicitsimports from the two examples are implicit ExecutionContext instances, which are needed to call thefutureandscheduleOncemethods. For exploratory purposes, it doesn't matter which one you use. Theglobalone from the scala library contains (iirc) a thread pool with 8 or so threads. I would guess that the play one is similar. Unless you are being extra-careful about which threads do what work, the choice should not affect you.