Пакет scala.concurrent
пакет concurrent
Члены типов
тракт Awaitable[+T] extends AnyRef
Объект, который, в конечном итоге, может быть завершён значением типа T , которое можно ожидать с помощью методов блокирования.
Объект Await предоставляет методы, позволяющие получить результат Awaitable, блокируя текущий поток до завершения Awaitable или наступления таймаута.
тракт 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( msg = ... )
тип CancellationException = java.util.concurrent.CancellationException
класс Channel[A] extends AnyRef
Этот класс предоставляет простую очередь FIFO объектов данных, которые считываются одним или несколькими потоками чтения.
- A
тип обмениваемых данных
класс DelayedLazyVal[T] extends AnyRef
DelayedLazyVal — это обёртка для длительных вычислений, имеющих валидный частично вычисленный результат.
Первый аргумент — функция получения результата в любой момент времени, а второй — длительное вычисление. После завершения вычисления метод apply перестанет перевычислять его и вернёт фиксированное значение с этого момента.
- С момента
2.8
тракт ExecutionContext extends AnyRef
ExecutionContext может асинхронно выполнять логику программы, обычно, но не обязательно, в пуле потоков.
Универсальный ExecutionContext должен быть асинхронным при выполнении любого Runnable , переданного в метод 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( msg = ... )
тракт ExecutionContextExecutor extends ExecutionContext with Executor
тракт ExecutionContextExecutorService extends ExecutionContextExecutor with ExecutorService
тип ExecutionException = java.util.concurrent.ExecutionException
тракт Future[+T] extends Awaitable[T]
A Future представляет значение, которое может или не может *в данный момент* быть доступно, но будет доступно в какой-то момент, или исключение, если это значение не может быть сделано доступным.
Асинхронные вычисления, которые возвращают значения типа Future, создаются с помощью вызова Future.apply и вычисляются с использованием предоставленного ExecutionContext, который может быть поддерживаемым пулом потоков.
import ExecutionContext.Implicits.global
val s = "Hello"
val f: Future[String] = Future {
s + " future!"
}
f foreach {
msg => println(msg)
}
- См. также
trait OnCompleteRunnable extends AnyRef
Маркер, указывающий, что java.lang.Runnable, предоставленный scala.concurrent.ExecutionContext, оборачивает обратный вызов, предоставленный Future.onComplete. Все обратные вызовы, предоставленные Future, в конечном итоге проходят через onComplete, поэтому это позволяет ExecutionContext специально обрабатывать обратные вызовы, которые были выполнены Future, если это необходимо.
trait Promise[T] extends AnyRef
class SyncChannel[A] extends AnyRef
SyncChannel позволяет синхронно обмениваться данными между потоком чтения и потоком записи. Поток записи блокируется до тех пор, пока данные, подлежащие записи, не будут прочитаны соответствующим потоком чтения.
- С момента
2.0
class SyncVar[A] extends AnyRef
Класс для обеспечения безопасного конкуретного доступа к изменяемой ячейке. Все методы синхронизированы.
- A
тип содержащегося значения
type TimeoutException = java.util.concurrent.TimeoutException
class Lock extends AnyRef
Этот класс ...
- Аннотации
- @deprecated
- Устарело
(С версии 2.11.2) используйте java.util.concurrent.locks.Lock
Члены значений
def blocking[T](body: ⇒ T): T
Используется для обозначения фрагмента кода, который потенциально блокирует, позволяя текущему BlockContext настраивать поведение среды выполнения. Правильное помечание блокирующего кода может улучшить производительность или предотвратить тупики.
Блокировка на Awaitable должна выполняться с использованием Await.result вместо blocking.
- body
Фрагмент кода, который содержит потенциально блокирующие или длительные вызовы.
- Аннотации
- @throws( clazz = classOf[Exception] )
- Исключения
-
CancellationExceptionесли вычисление было отмененоInterruptedExceptionв случае прерывания ожидания в рамках блокирующегоbody
object Await
Await используется для обеспечения надлежащей обработки блокировки для экземпляров Awaitable.
Хотя иногда полезно, например, для тестирования, рекомендуется по возможности избегать Await — вместо этого предпочтительнее использовать комбинаторы и/или обратные вызовы. Методы Await's result и ready блокируют выполнение вызывающего потока до тех пор, пока они не вернутся, что приведет к снижению производительности и, возможно, проблемам тупика.
object BlockContext
object ExecutionContext
object Future
object JavaConversions
object Promise
© 2002-2019 EPFL, with contributions from Lightbend.
Licensed under the Apache License, Version 2.0.
https://www.scala-lang.org/api/2.12.9/scala/concurrent/index.html
Этот пакет содержит базовые элементы для конкурентного и параллельного программирования.
Руководство
Более подробное руководство по Future и Promise, включая обсуждение и примеры, можно найти по адресу http://docs.scala-lang.org/overviews/core/futures.html.
Общие импорты
При работе с Future часто удобно импортировать весь пакет concurrent:
При использовании таких элементов, как
Futures, часто необходимо наличие неявногоExecutionContext. Общие рекомендации по этим неявным параметрам следующие.Если код представляет собой определение класса или метода, и неявный
ExecutionContextне доступен, запросите его у вызывающей стороны, добавив список неявных параметров:def myMethod(myParam: MyType)(implicit ec: ExecutionContext) = … //Or class MyClass(myParam: MyType)(implicit ec: ExecutionContext) { … }Это позволяет вызывающей стороне метода или создателю экземпляра класса решить, какой
ExecutionContextследует использовать.Для типичного использования REPL и экспериментов часто желательно импортировать глобальный
ExecutionContext.Указание продолжительности
Операции часто требуют указания продолжительности. Доступен DSL для продолжительности, чтобы упростить их определение:
Использование Future для асинхронного вычисления
Базовое использование Future простое с помощью фабричного метода на 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 и конкурентностью, чтобы избежать потенциальных тупиков и улучшить производительность. Вместо этого используйте обратные вызовы или комбинаторы, чтобы оставаться в домене Future:
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") }