Есть ли способ получить неглобальный клон scala.concurrent.ExecutionContext.global?

Я ищу неглобальный экземпляр ForkJoinPool, чтобы получить весь отличный параллелизм по умолчанию и семантику выполнения глобального экземпляра с возможностью управления жизненным циклом пула.

Я заглянул в исходный код scala.concurrent и scala.concurrent.impl, и, к сожалению, похоже, что весь код, создающий экземпляр по умолчанию, — это private[scala.concurrent], и нет никакого косвенного способа вызвать этот код.

Я могу получить только новый экземпляр ExecutionContext с настройками по умолчанию, используя ExecutionContext.fromExecutor(null), но нет никакого способа получить базовый ForkJoinPool. Также нет способа отключить ExecutionContext напрямую.

Делаю ли я что-то эзотерическое, чего мне не следует делать? Потому что мне кажется естественным хотеть: семантику/конфигурацию чего-то по умолчанию без его глобальности.


person Erik Kaplun    schedule 05.04.2014    source источник


Ответы (2)


Дело не в доступе, а в форме. Хвост слона:

scala> type ECI = { def createExecutorService: ExecutorService }
defined type alias ECI

scala> val fjp = ExecutionContext.global.asInstanceOf[ECI].createExecutorService
fjp: java.util.concurrent.ExecutorService = scala.concurrent.forkjoin.ForkJoinPool@606dff1[Running, parallelism = 8, size = 0, active = 0, running = 0, steals = 0, tasks = 0, submissions = 0]

или бесформенно:

scala> import shapeless.syntax.typeable._
import shapeless.syntax.typeable._

scala> val fjp = concurrent.ExecutionContext.global.cast[ECI] map (_.createExecutorService) getOrElse ???
fcp: java.util.concurrent.ExecutorService = scala.concurrent.forkjoin.ForkJoinPool@45c26421[Running, parallelism = 8, size = 0, active = 0, running = 0, steals = 0, tasks = 0, submissions = 0]

а потом

scala> val eces = ExecutionContext fromExecutorService fjp
eces: scala.concurrent.ExecutionContextExecutorService = scala.concurrent.impl.ExecutionContextImpl$$anon$1@1df3794c

scala> eces.shutdown
person som-snytt    schedule 07.04.2014
comment
не знаю, как я пропустил то, что это так просто... большое спасибо! :) - person Erik Kaplun; 07.04.2014

Преимущество private[path.to.package] в том, что его можно обойти, просто притворившись, что вы находитесь внутри этого пакета:

package scala.concurrent

import java.util.concurrent.Executor

object Foo {
  implicit lazy val myGlobalExecutionContext: ExecutionContextExecutor =
    impl.ExecutionContextImpl.fromExecutor(null: Executor)
}

Однако имейте в виду, что если вы сделаете это, вы больше не будете в сфере общедоступного API и вам придется столкнуться с некоторыми несовместимостями при изменении версии scala.

person Christian Krause    schedule 05.04.2014
comment
Хорошо, это очевидно; на самом деле не думал об этом раньше :) кстати, ваш код по-прежнему не получает сам пул по умолчанию, только контекст выполнения по умолчанию, но я думаю, я мог бы адаптировать его для получения базового пула. - person Erik Kaplun; 05.04.2014
comment
Я также не знал об этой функции несколько часов назад, пока не посмотрел последние скалаваги. эпизоды, в которых Джош Суэрет объясняет, почему он существует и как он может быть смехотворно полезен. - person Christian Krause; 05.04.2014
comment
Я пока не принимаю / не голосую, чтобы посмотреть, смогу ли я получить из этого какие-то другие мнения; если нет, представитель ваш. - person Erik Kaplun; 05.04.2014