斯卡拉之間的差異有其執行上下文作爲是什麼Scala的執行上下文和遊戲的執行上下文
import scala.concurrent.ExecutionContext.Implicits.global
答打法有自己的執行上下文
import play.api.libs.concurrent.Execution.Implicits.defaultContext
請告訴我的主要區別是哪一個我們是否應該使用和在哪個senario中。
斯卡拉之間的差異有其執行上下文作爲是什麼Scala的執行上下文和遊戲的執行上下文
import scala.concurrent.ExecutionContext.Implicits.global
答打法有自己的執行上下文
import play.api.libs.concurrent.Execution.Implicits.defaultContext
請告訴我的主要區別是哪一個我們是否應該使用和在哪個senario中。
scala.concurrent.ExecutionContext.Implicits.global
(斯卡拉標準庫執行上下文)是標準斯卡拉庫提供的執行上下文。這是一個特殊的ForkJoinPool,它使用阻塞方法來處理潛在的阻塞代碼,以便在池中產生新線程。您不應該在播放應用程序中使用它,因爲播放無法控制它。play.api.libs.concurrent.Execution.Implicits.defaultContext
(Play執行上下文)使用actor dispatcher
。這是應該用於播放應用程序的內容。除了播放執行上下文之外,將阻塞調用卸載到不同的執行上下文也是一種好的做法。這樣可以避免遊戲程序進入飢餓狀態。 IMPLplay.api.libs.concurrent.Execution.Implicits.defaultContext
val appOrNull: Application = Play._currentApp appOrNull match { case null => common case app: Application => app.actorSystem.dispatcher } private val common = ExecutionContext.fromExecutor(new ForkJoinPool())
當應用程序不爲空,它使用
actorSystem.dispatcher
斯卡拉標準執行上下文
播放執行上下文。
val executor: Executor = es match {
case null => createExecutorService
case some => some
}
該方法創建的執行程序服務考慮到available processors
和讀取配置。
def createExecutorService: ExecutorService = {
def getInt(name: String, default: String) = (try System.getProperty(name, default) catch {
case e: SecurityException => default
}) match {
case s if s.charAt(0) == 'x' => (Runtime.getRuntime.availableProcessors * s.substring(1).toDouble).ceil.toInt
case other => other.toInt
}
def range(floor: Int, desired: Int, ceiling: Int) = scala.math.min(scala.math.max(floor, desired), ceiling)
val desiredParallelism = range(
getInt("scala.concurrent.context.minThreads", "1"),
getInt("scala.concurrent.context.numThreads", "x1"),
getInt("scala.concurrent.context.maxThreads", "x1"))
val threadFactory = new DefaultThreadFactory(daemonic = true)
try {
new ForkJoinPool(
desiredParallelism,
threadFactory,
uncaughtExceptionHandler,
true) // Async all the way baby
} catch {
case NonFatal(t) =>
System.err.println("Failed to create ForkJoinPool for the default ExecutionContext, falling back to ThreadPoolExecutor")
t.printStackTrace(System.err)
val exec = new ThreadPoolExecutor(
desiredParallelism,
desiredParallelism,
5L,
TimeUnit.MINUTES,
new LinkedBlockingQueue[Runnable],
threadFactory
)
exec.allowCoreThreadTimeOut(true)
exec
}
}
此代碼負責管理阻塞。嘗試在代碼中遇到blocking
時創建新線程。
// Implement BlockContext on FJP threads
class DefaultThreadFactory(daemonic: Boolean) extends ThreadFactory with ForkJoinPool.ForkJoinWorkerThreadFactory {
def wire[T <: Thread](thread: T): T = {
thread.setDaemon(daemonic)
thread.setUncaughtExceptionHandler(uncaughtExceptionHandler)
thread
}
def newThread(runnable: Runnable): Thread = wire(new Thread(runnable))
def newThread(fjp: ForkJoinPool): ForkJoinWorkerThread = wire(new ForkJoinWorkerThread(fjp) with BlockContext {
override def blockOn[T](thunk: =>T)(implicit permission: CanAwait): T = {
var result: T = null.asInstanceOf[T]
ForkJoinPool.managedBlock(new ForkJoinPool.ManagedBlocker {
@volatile var isdone = false
override def block(): Boolean = {
result = try thunk finally { isdone = true }
true
}
override def isReleasable = isdone
})
result
}
})
}