Spec-Zone.ru › Scala 3.1

Объект scala.concurrent.ExecutionContext

Класс-компаньон • Исходный код

объект ExecutionContext

Содержит методы-фабрики для создания контекстов выполнения.

Супертипы
класс Object
трайт Matchable
класс Any
Тип самого объекта
ExecutionContext.type

Классы-объекты

Исходный код
объект Implicits

Исходный код
объект parasitic extends ExecutionContextExecutor

ПРЕДУПРЕЖДЕНИЕ: Выполняйте только код, который быстро вернёт управление вызывающему методу.

Этот ExecutionContext забирает время выполнения у других потоков, выполняя свои Runnable в Thread, вызывая execute, а затем возвращая управление вызывающему методу после выполнения *всех* своих Runnable. Вложенные вызовы execute будут перепрыгивать, чтобы предотвратить неконтролируемый рост стека.

При использовании parasitic с абстракциями, такими как Future, в многих случаях будет непредсказуемо, какой Thread будет выполнять логику, так как это зависит от того, когда/если данный Future будет завершён.

Не вызывайте блокирующий код в Runnable методах, переданных в этот ExecutionContext, так как это помешает прогрессу других ожидающих Runnable и вызывающему Thread.

Симптомы неправильного использования этого ExecutionContext включают, но не ограничиваются, тупиками и серьёзными проблемами производительности.

Любые NonFatal или InterruptedException будут сообщены defaultReporter.

Конкретные методы

Исходный код
def fromExecutor(e: Executor, reporter: Throwable => Unit): ExecutionContextExecutor

Создаёт ExecutionContext из данного Executor.

Параметры
e

используемый Executor. Если null, создаётся новый Executor с стандартной конфигурацией.

reporter

функция для отчёта об ошибках

Возвращает

ExecutionContext, использующий данный Executor

Исходный код
def fromExecutor(e: Executor): ExecutionContextExecutor

Создаёт ExecutionContext из данного Executor с стандартным отчётом об ошибках.

Параметры
e

используемый Executor. Если null, создаётся новый Executor с стандартной конфигурацией.

Возвращает

ExecutionContext, использующий данный Executor

Исходный код
def fromExecutorService(e: ExecutorService, reporter: Throwable => Unit): ExecutionContextExecutorService

Создаёт ExecutionContext из данного ExecutorService.

Параметры значения
e

используемый ExecutorService. Если null, создаётся новый ExecutorService с настройками по умолчанию.

reporter

функция для отчётности об ошибках

Возвращает

ExecutionContext с использованием заданного ExecutorService

Исходный код
def fromExecutorService(e: ExecutorService): ExecutionContextExecutorService

Создаёт ExecutionContext из заданного ExecutorService с отчётностью по умолчанию.

Если гарантируется, что ни одна из выполняемых задач не блокируется, для создания ExecutionContext можно использовать однопоточное ExecutorService следующим образом:

import java.util.concurrent.Executors
val ec = ExecutionContext.fromExecutorService(Executors.newSingleThreadExecutor())
Параметры значения
e

используемый ExecutorService. Если null, создаётся новый ExecutorService с настройками по умолчанию.

Возвращает

ExecutionContext с использованием заданного ExecutorService

Конкретные поля

Исходный код
final val defaultReporter: Throwable => Unit

Отчётность по умолчанию просто выводит трассировку стека Throwable в System.err.

Возвращает

функцию для отчётности об ошибках

Исходный код
final lazy val global: ExecutionContextExecutor

Глобальный ExecutionContext. Эта реализация ExecutionContext по умолчанию поддерживается пулом потоков с воровством задач. Её можно настроить с помощью следующих системных свойств:

  • scala.concurrent.context.minThreads = по умолчанию "1"

  • scala.concurrent.context.numThreads = по умолчанию "x1" (то есть текущее количество доступных процессоров * 1)

  • scala.concurrent.context.maxThreads = по умолчанию "x1" (то есть текущее количество доступных процессоров * 1)

  • scala.concurrent.context.maxExtraThreads = по умолчанию "256"

Размер пула потоков затем numThreads ограничен minThreads снизу и maxThreads сверху.

maxExtraThreads — максимальное количество дополнительных потоков в любой момент времени для предотвращения тупика, см. scala.concurrent.blocking.

Контекст выполнения global может быть использован явно, определением implicit val ec: scala.concurrent.ExecutionContext = scala.concurrent.ExecutionContext.global, или импортом ExecutionContext.Implicits.global.

Группировка кратковременных вложенных задач

Асинхронный код с кратковременными вложенными задачами выполняется эффективнее при использовании ExecutionContext.opportunistic (продолжайте чтение, чтобы узнать, почему это private[scala] и как к нему получить доступ).

ExecutionContext.opportunistic использует тот же пул потоков, что и ExecutionContext.global. Он пытается сгруппировать вложенные задачи и выполнить их в том же потоке, что и окружающая задача. Это идеально подходит для выполнения кратковременных задач, так как это уменьшает накладные расходы на переключение контекста.

ПРЕДУПРЕЖДЕНИЕ: длительные и/или блокирующие задачи должны быть обозначены в scala.concurrent.blocking-блоках, чтобы убедиться, что любые ожидающие задачи в текущей группе могут быть выполнены другим потоком в global.

Как использовать

Это поле private[scala] для сохранения бинарной совместимости. Оно было добавлено в 2.13.4, код, который ссылается на него напрямую, не работает с Scala библиотекой 2.13.0-3.

Библиотеки не должны ссылаться на это поле напрямую, потому что пользователи библиотеки могут использовать более раннюю версию Scala. Для использования группирующего ExecutionContext в библиотеке код должен использовать global в случае отсутствия поля opportunistic (пример ниже). Результирующий ExecutionContext имеет поведение группировки во всех версиях Scala 2.13 (global имеет группировку в 2.13.0-3).

implicit val ec: scala.concurrent.ExecutionContext = try {
 scala.concurrent.ExecutionContext.getClass
   .getDeclaredMethod("opportunistic")
   .invoke(scala.concurrent.ExecutionContext)
   .asInstanceOf[scala.concurrent.ExecutionContext]
} catch {
 case _: NoSuchMethodException =>
   scala.concurrent.ExecutionContext.global
}

Авторы приложений могут безопасно использовать это поле, потому что версия Scala во время выполнения такая же, как и во время компиляции. Варианты обхода ограничения доступа включают:

  1. Использование структурного типа (пример ниже). Это использует рефлексию во время выполнения.

  2. Написание Scala object в пакете scala (пример ниже).

  3. Написание файла исходного кода Java. Это работает, потому что private[scala] излучается как public в байткоде Java.

// Option 1
implicit val ec: scala.concurrent.ExecutionContext =
 (scala.concurrent.ExecutionContext:
   {def opportunistic: scala.concurrent.ExecutionContextExecutor}
 ).opportunistic

// Option 2
package scala {
 object OpportunisticEC {
   implicit val ec: scala.concurrent.ExecutionContext =
     scala.concurrent.ExecutionContext.opportunistic
 }
}
Возвращает

глобальное ExecutionContext

© 2002-2022 EPFL, with contributions from Lightbend.
Licensed under the Apache License, Version 2.0.
https://scala-lang.org/api/3.1.1/scala/concurrent/ExecutionContext$.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API