Пакет scala.concurrent
пакет concurrent
Члены пакета
пакет duration
Типовые члены
трайт Awaitable[+T] extends AnyRef
Объект, который может быть в конечном итоге завершен значением типа T , которое может быть ожидаемо с помощью методов блокировки.
Объект Await предоставляет методы, которые позволяют получить результат Awaitable , блокируя текущий поток, пока Awaitable не будет завершен или не наступит таймаут.
трайт Batchable extends AnyRef
трайт BlockContext extends AnyRef
Контекст, уведомляемый scala.concurrent.blocking , когда поток собирается заблокироваться. По сути, этот трайт предоставляет реализацию для scala.concurrent.Await. scala.concurrent.Await.result() и scala.concurrent.Await.ready() находят экземпляр BlockContext , сначала проверив, предоставлен ли он через BlockContext.withBlockContext(), а если нет, то проверяя, является ли Thread.currentThread экземпляром BlockContext. Таким образом, пул потоков может иметь свои экземпляры java.lang.Thread , реализующие BlockContext. Если поток не реализует BlockContext, используется по умолчанию BlockContext.
Как правило, вам следует продолжать цепочку с предыдущим BlockContext, как показано ниже:
val oldContext = BlockContext.current
val myContext = new BlockContext {
override def blockOn[T](thunk: =>T)(implicit permission: CanAwait): T = {
// you'd have code here doing whatever you need to do
// when the thread is about to block.
// Then you'd chain to the previous context:
oldContext.blockOn(thunk)
}
}
BlockContext.withBlockContext(myContext) {
// then this block runs with myContext as the handler
// for scala.concurrent.blocking
}
sealed трайт CanAwait extends AnyRef
Этот маркерный трайт используется объектом Await для обеспечения того, что Awaitable.ready и Awaitable.result не вызываются напрямую кодом пользователя. Неявный экземпляр этого трайта доступен только тогда, когда код пользователя в настоящее время вызывает методы объекта Await.
- Аннотации
- @implicitNotFound("Не вызывайте методы `Awaitable` напрямую, используйте объект `Await`.")
тип CancellationException = java.util.concurrent.CancellationException
трайт ExecutionContext extends AnyRef
ExecutionContext может асинхронно выполнять логику программы, обычно, но не обязательно, в пуле потоков.
Объект общего назначения ExecutionContext должен быть асинхронным при выполнении любого действия, передаваемого в его метод execute. Специализированный ExecutionContext может быть синхронным, но должен передаваться только коду, который явно безопасен для выполнения с помощью синхронно выполняющего ExecutionContext.
API, такие как Future.onComplete , требуют от вас предоставления обратного вызова и неявного ExecutionContext. Неявный ExecutionContext будет использоваться для выполнения обратного вызова.
Хотя можно просто импортировать scala.concurrent.ExecutionContext.Implicits.global для получения неявного ExecutionContext, разработчики приложений должны внимательно подумать, где им необходимо установить политику выполнения; в идеале, в одном месте на приложение (или в связанном по логике разделе кода) принимается решение о выборе используемого ExecutionContext. То есть вы, как правило, хотите избегать жёсткого кодирования, особенно через импорт, scala.concurrent.ExecutionContext.Implicits.global. Рекомендуемый подход — добавить (implicit ec: ExecutionContext) к методам или параметрам конструктора класса, которым нужен ExecutionContext.
Затем локально импортируйте определенный ExecutionContext в одном месте для всего приложения или модуля, неявно передавая его в отдельные методы. В качестве альтернативы, определите локальную неявную переменную val с необходимым ExecutionContext.
Может быть уместен пользовательский ExecutionContext для выполнения кода, который блокируется на ввода-выводе или выполняет длительные вычисления. ExecutionContext.fromExecutorService и ExecutionContext.fromExecutor — хорошие способы создания пользовательского ExecutionContext.
Целью ExecutionContext является лексическое ограничение выполнения кода. То есть каждый метод, класс, файл, пакет или приложение определяет, как выполнять свой собственный код. Это предотвращает проблемы, такие как выполнение обратных вызовов приложения в пуле потоков, принадлежащем библиотеке сетевого взаимодействия. Размер пула потоков библиотеки сетевого взаимодействия можно безопасно настроить, зная, что затрагиваются только сетевые операции этой библиотеки. Выполнение обратных вызовов приложения можно настроить отдельно.
- Аннотации
-
@implicitNotFound("""Не найдено неявное ExecutionContext. Вы можете передать
параметр (implicit ec: ExecutionContext) в ваш метод.
ExecutionContext используется для настройки того, как и на каких
пулах потоков будут выполняться Futures, поэтому выбранный
конкретный ExecutionContext важен.
Если ваше приложение не определяет ExecutionContext в другом месте,
рассмотрите возможность использования глобального ExecutionContext Scala
путем определения следующего:
implicit val ec: scala.concurrent.ExecutionContext = scala.concurrent.ExecutionContext.global""")
трайт ExecutionContextExecutor extends ExecutionContext with Executor
трайт ExecutionContextExecutorService extends ExecutionContextExecutor with ExecutorService
тип ExecutionException = java.util.concurrent.ExecutionException
трайт Future[+T] extends Awaitable[T]
Future представляет собой значение, которое может или не может быть *в настоящее время* доступно, но будет доступно в какой-то момент, или исключение, если это значение не может быть сделано доступным.
Асинхронные вычисления, которые возвращают futures, создаются с помощью вызова Future.apply и вычисляются с использованием предоставленного ExecutionContext, который может быть основан на пуле потоков.
import ExecutionContext.Implicits.global
val s = "Hello"
val f: Future[String] = Future {
s + " future!"
}
f foreach {
msg => println(msg)
}
- См. также
описание Promise[T] extends AnyRef
Promise — это объект, который может быть завершен значением или провален исключением.
Promise всегда должен быть в конечном итоге завершен, независимо от успеха или ошибки, чтобы избежать непреднамеренного удержания ресурсов для любых связанных функций обратного вызова или преобразований.
тип TimeoutException = java.util.concurrent.TimeoutException
Члены-значения
final def blocking[T](body: => T): T
Используется для обозначения фрагмента кода, который потенциально блокирует, позволяя текущему BlockContext настраивать поведение среды выполнения. Правильное маркирование блокирующего кода может улучшить производительность или предотвратить тупиковые ситуации.
Блокировка на Awaitable должна выполняться с использованием Await.result вместо blocking.
- body
Фрагмент кода, содержащий потенциально блокирующие или длительные вызовы.
- Аннотации
- @throws(classOf[Exception])
- Исключения
-
CancellationException, если вычисление было отмененоInterruptedException, если ожидание внутри блокирующегоbodyбыло прервано
объект Await
Await используется для обеспечения правильной обработки блокировки для экземпляров Awaitable.
Хотя иногда полезно, например, для тестирования, рекомендуется по возможности избегать Await — вместо этого отдавайте предпочтение комбинаторам и/или обратным вызовам. Методы result и ready Await будут блокировать выполнение вызывающей нити до их возврата, что приведет к снижению производительности и, возможно, к тупиковой ситуации.
объект BlockContext
объект ExecutionContext
объект Future
объект Promise
© 2002-2019 EPFL, with contributions from Lightbend.
Licensed under the Apache License, Version 2.0.
https://www.scala-lang.org/api/2.13.0/scala/concurrent/index.html
В этом объекте пакета содержатся примитивы для конкурентного и параллельного программирования.
Руководство
Более подробное руководство по будущим (Futures) и обещаниям (Promises), включая обсуждение и примеры, можно найти по адресу http://docs.scala-lang.org/overviews/core/futures.html.
Общие импорты
При работе с будущими (Futures) часто удобно импортировать весь пакет concurrent:
При использовании таких элементов, как
Futures, часто требуется явноеExecutionContextв области видимости. Общие рекомендации по этим имплиситам следующие.Если код представляет собой определение класса или метода и нет доступного
ExecutionContext, запросите его у вызывающего элемента, добавив список неявных параметров:def myMethod(myParam: MyType)(implicit ec: ExecutionContext) = … //Or class MyClass(myParam: MyType)(implicit ec: ExecutionContext) { … }Это позволяет вызывающему методу или создателю экземпляра класса решить, какой
ExecutionContextследует использовать.Для типичного использования REPL и экспериментов часто желательно импортировать глобальный
ExecutionContext.Указание продолжительности
Операции часто требуют указания продолжительности. Доступен DSL для продолжительности, чтобы упростить определение этих значений:
Использование Futures для неблокирующих вычислений
Базовое использование будущих (futures) просто с помощью фабричного метода на Future, который асинхронно выполняет предоставленную функцию, возвращая вам будущий результат этой функции, не блокируя текущий поток. Для создания Future вам потребуется либо явное, либо неявное ExecutionContext:
import scala.concurrent._ import ExecutionContext.Implicits.global // implicit execution context val firstZebra: Future[Int] = Future { val source = scala.io.Source.fromFile("/etc/dictionaries-common/words") source.toSeq.indexOfSlice("zebra") }Избегайте блокировок
Хотя блокировка возможна для ожидания результатов (с обязательной продолжительностью таймаута):
и хотя это иногда необходимо, особенно для целей тестирования, блокирование в целом не рекомендуется при работе с Future и параллельными вычислениями, чтобы избежать потенциальных тупиков и улучшить производительность. Вместо этого используйте обратные вызовы или комбинаторы, чтобы оставаться в области будущих (futures):
val animalRange: Future[Int] = for { aardvark <- firstAardvark zebra <- firstZebra } yield zebra - aardvark animalRange.onSuccess { case x if x > 500000 => println("It's a long way from Aardvark to Zebra") }