В чем разница между контекстом исполнения scala и контекстом исполнения игры

Scala имеет контекст выполнения как

import scala.concurrent.ExecutionContext.Implicits.global

Ans Play имеет свой собственный контекст выполнения

import play.api.libs.concurrent.Execution.Implicits.defaultContext

В чем главное отличие, и какой из них использовать и в каком сенарио?

1 ответ

Решение

scala.concurrent.ExecutionContext.Implicits.global (Контекст выполнения Scala std lib) - это контекст выполнения, предоставляемый стандартной библиотекой scala. Это специальный ForkJoinPool, который использует метод блокировки для обработки потенциально блокирующего кода с целью создания новых потоков в пуле. Вы не должны использовать это внутри игрового приложения, так как игра не будет иметь над ним никакого контроля. В то время как play.api.libs.concurrent.Execution.Implicits.defaultContext (Воспроизвести контекст выполнения) использует actor dispatcher, Это то, что следует использовать для игровых приложений. Также рекомендуется выгрузить блокирующие вызовы в другой контекст выполнения, отличный от контекста воспроизведения. Таким образом, приложение не попадет в голодное состояние.

Воспроизведение контекста исполнения play.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

Scala стандартный контекст исполнения.

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
      }
    })
  }
Другие вопросы по тегам