Готовый перевод Futures and Promises / Фьючи и Промисы: Futures
Фьюча - это объект хранящий значение, которое может быть доступным в какой-то момент времени. Обычно, это значение является результатом какого-то вычисления:
Если вычисление еще не завершено, мы говорим что фьюча не завершена(разрешена).
Если вычисление завершено со значением или с исключением, то мы говорим что фьюча завершена(разрешена).
Завершение может принимать одну из двух видов:
Когда фьюча заврешена со значением, мы говорим что она была завершена(разрешена) успешно с этим значением.
Когда фьюча завершена с вызванным исключением в результате вычисления, мы говорим, что фьюча завершилась ошибкой (пофейлилась) с этим исключением.
Фьюча имеет важное свойство: она может быть присвоена (переменной) только один раз. В результате присвоения объекту фьючи значения или исключения, объект становится неизменяемым и не может быть переопределен.
Самый простой способ создать объект фьючи - вызвать метод future, который начинает асинхронное вычисление и возвращает фьючу, хранящую результат этого вычисления. Значение становится доступны сразу после завершения фьючи.
Обратите внимание, что Future[T] это тип который определяет объект фьючи в то время как future это метод, который создает и планирует асинхронное вычисление и затем возвращает объект фьючи, который будет выполнен со значением этого вычисления.
Лучше всего это показать примером.
Предположим, что мы хотим использовать гипотетическое API некой популярной социальной сети для получения списка друзей пользователя. Мы создаем новую сессию и посылаем запрос для получения списка друзей определенного пользователя:
import scala.concurrent._
import ExecutionContext.Implicits.global
val session = socialNetwork.createSessionFor("user", credentials)
val f: Future[List[Friend]] = future {
session.getFriends()
}
Выше, мы сначала импортируем содержимое пакета scala.concurrent для того чтобы нам доступен тип Future и конструктор фьюч. Второй impot мы объясним скоро.
Затем мы инициализируем переменную сессии, которую мы будем использовать для отсылки запросов на сервер, используя гипотетический метод createSessionFor, который возвращает объект типа List[Friend]. Для получения списка друзей пользователя, запрос посылается по сети, а это может занимать продолжительное время. Это показано при помощи вызова метода getFriends. Для оптимального использования ЦПУ до тех пор пока ответ не будет получен, мы не должны блокировать остальную часть программы, это вычисление должно быть отложено асинхронно. И именно это и делает метод future - он выполняет указанное вычисление конкурентно, в данном случае, посылает запрос на сервер и ждет ответ.
Список друзей становится доступным в фьюче f сразу как сервер ответит.
Неуспешный попытка может привести к исключению. В следующем примере сессия некорректно инициализирована, и поэтому вычисление в блоке future вызовет NullPointerException. Здесь фьюча f завершится исключением, а не будет выполнена успешно:
val session = null
val f: Future[List[Friend]] = future {
session.getFriends
}
Строка import ExecutionContext.Implicits.global импортирует глобальный контекст выполнения по умолчанию. Контексты выполнения выполняет задачи, которые подчиняются им (относятся к ним), и вы можете думать об контекстах выполнения как пуле тредов. Они присущи для метода future потому что они управляют как и когда асинхронное вычисление будет выполнено. Вы можете определить свои собственные контексты выполнения и использовать их со фьючами, но пока достаточно знать что вы можете импортировать контекст вычисления по умолчанию как показано выше.
Наш пример основан на API гипотетической социальной сети, где вычисление состоит из отслыки сетевого запроса и ожидания ответа. Честно было бы показать пример с асинхронными вычислениями, которое вы могли бы попробовать "из коробки". Предположим у вас есть текстовый файл и вы хотите найти ближайшее место, в котором находится определенное слово. Это вычисление может вызывать блокировки во время получения содержимого файла с диска, и поэтому имеет смысл выполнять его конкурентно с остальными вычислениями.
val firstOccurrence: Future[Int] = future {
val source = scala.io.Source.fromFile("myText.txt")
source.toSeq.indexOfSlice("myKeyword")
}
Внимание! Этот перевод, возможно, ещё не готов.
Его статус: идёт перевод
Переведено на Нотабеноиде
http://notabenoid.org/book/44566/176067
Переводчики: 2heoh
Настройки
Готово:
