Play的执行上下文vs scala全局

bjf*_*her 28 scala playframework

如何执行上下文

import scala.concurrent.ExecutionContext.Implicits.global
Run Code Online (Sandbox Code Playgroud)

与Play的执行上下文不同:

import play.core.Execution.Implicits.{internalContext, defaultContext}
Run Code Online (Sandbox Code Playgroud)

Mic*_*jac 44

他们是非常不同的.

在Play 2.3.x和之前的版本中,play.core.Execution.Implicits.internalContext是一个ForkJoinPool固定的大小限制,由Play内部使用.您永远不应该将它用于您的应用程序代码.来自文档:

播放内部线程池 - 这由Play内部使用.此线程池中的线程不应执行任何应用程序代码,并且不应在此线程池中执行任何阻止.可以通过在application.conf中设置internal-threadpool-size来配置其大小,默认为可用处理器的数量.

相反,你会使用play.api.libs.concurrent.Execution.Implicits.defaultContext,它使用ActorSystem.

在2.4.x中,它们都使用相同的ActorSystem.这意味着Akka将在其自己的线程池中分配工作,但是以一种对您来说不可见的方式(除了配置).几个Akka演员可以共享同一个帖子.

scala.concurrent.ExecutionContext.Implicits.globalExecutionContextScala标准库中定义的.ForkJoinPool使用该blocking方法处理可能阻塞的代码以便在池中生成新线程是一种特殊的方法.你真的不应该在Play应用程序中使用它,因为Play无法控制它.如果你不小心的话,它也有可能产生大量的线程并使用大量的内存.

scala.concurrent.ExecutionContext.Implicits.global这个答案中写了更多.


evg*_*mon 8

它们是相同的,并指向Play或Akka或组合应用程序中基础actor系统的默认调度程序.

默认播放的上下文

play.api.libs.concurrent.Execution.Implicits.defaultContext
Run Code Online (Sandbox Code Playgroud)

播放的内部背景

play.core.Execution.Implicits.internalContext
Run Code Online (Sandbox Code Playgroud)

Guice的EC注入

class ClassA @Inject()(config: Configuration)
                           (implicit ec: ExecutionContext) {
...
}
Run Code Online (Sandbox Code Playgroud)

但这是不同的:

scala.concurrent.ExecutionContext.Implicits.global
Run Code Online (Sandbox Code Playgroud)

此外,数据库驱动程序,例如,如果您使用光滑,可能会提出自己的执行上下文.无论如何,


最佳实践:

  • scala.concurrent.ExecutionContext.Implicits.global当你在游戏或akka框架中时,不要使用这种方式,在高负载时你可能会使用比最佳线程更多的线程,因此性能可能会降低.
  • 别怕!除非你做一些阻塞任务,例如监听网络连接,或明确地从db中读取,使你"当前threed"等待结果,否则你可以随意使用默认的调度程序.
  • 从默认执行程序开始,如果您发现Play/Akka在高负载期间响应不佳,请切换到新的线程池以进行耗时的计算任务.
    • 长时间的计算任务通常不被视为阻塞.例如,遍历内存中的自动完成树.但是,如果您希望在完成计算任务后让控制结构保持正常运行,则可能会认为它们已阻塞.
    • 当您将计算任务视为非阻塞时可能发生的坏事是,当所有线程在高负载下进行计算时,将暂停播放和Akka消息调度程序.单独的调度程序的优点是队列处理器不会饿死.具有单独调度程序的缺点是您可以分配更多最佳的线程,并且您的整体性能将会降低.
    • 不同之处在于高负载服务器,不用担心小项目,使用默认值
  • scala.concurrent.ExecutionContext.Implicits.global在应用程序中没有其他执行程序运行时使用.不要担心这是安全的.
  • 创建Futures后,使用默认池,这是最安全的方法,除非您确定未来是阻塞的.然后使用单独的池或尽可能使用blocking {}结构.
  • 创建一个单独的线程池一次
    • Await是一个未来
    • 你调用Thread.sleep
    • 您正在读取流/套接字/ http呼叫
    • 使用阻塞驱动程序手动查询数据库(通常是光滑的是安全的)
    • 安排任务在10秒内运行
    • 安排每秒运行一次的任务
  • 对于未来的映射/恢复操作,请使用默认执行程序,通常这是安全的
  • 使用默认调度程序时,异常处理是安全的
  • 总是在PlayAkka中随身携带Akka调度员,有一个很好的方法来定义一个新的调度员application.conf