Чем отличаются фьючерсы и обещания Clojure? - PullRequest
85 голосов
/ 07 января 2011

Фьючерсы и обещания блокируются, пока они не вычислили свои значения, так в чем же разница между ними?

Ответы [ 4 ]

50 голосов
/ 07 января 2011

Ответы в терминах Clojure, вот несколько примеров из скриншота Шона Девлина :

(def a-promise (promise))
(deliver a-promise :fred)

(def f (future (some-sexp)))
(deref f)

Обратите внимание, что в обещании вы явно предоставляете значение, которое вы выбрали в последующих вычислениях (:fred в этом случае). С другой стороны, будущее потребляется там же, где оно было создано. some-expr предположительно запускается за кулисами и рассчитывается в тандеме (в конце концов), но если он остается неопределенным к моменту обращения к блокам потоков, пока он не станет доступен.


отредактировано для добавления

Чтобы еще больше отличать обещание от будущего, обратите внимание на следующее:

обещание

  1. Вы создаете promise. Этот объект обещания теперь может быть передан в любой поток.
  2. Вы продолжаете вычисления. Это могут быть очень сложные вычисления, включающие побочные эффекты, загрузку данных, ввод данных пользователем, доступ к базе данных, другие обещания - все что угодно. Код будет очень похож на ваш основной код в любой программе.
  3. Когда вы закончите, вы можете deliver получить результаты для этого объекта обещания.
  4. Любой предмет, который попытается deref выполнить ваше обещание до того, как вы закончите свои вычисления, заблокируется, пока вы не закончите. Как только вы закончите и вы deliver измените обещание, обещание больше не будет блокироваться.

будущее

  1. Вы создаете свое будущее. Частью вашего будущего является выражение для расчета.
  2. Будущее может исполниться или не исполниться одновременно. Может быть назначен поток, возможно, из пула. Это может просто подождать и ничего не делать. С вашей точки зрения вы не можете сказать .
  3. В какой-то момент вы (или другая нить) deref видите будущее. Если расчет уже завершен, вы получите его результаты. Если он еще не завершен, вы блокируете, пока он не завершен. (Предположительно, если он еще не запущен, deref означает, что он начинает выполняться, но это тоже не гарантируется.)

Хотя вы могли бы сделать выражение в будущем таким же сложным, как и код, который следует за созданием обещания, сомнительно, что это желательно. Это означает, что фьючерсы действительно больше подходят для быстрых фоновых вычислений, в то время как обещания действительно больше подходят для больших и сложных путей выполнения. Кроме того, обещания кажутся с точки зрения доступных расчетов немного более гибкими и ориентированными на создателя обещаний, выполняющего работу, и на другой поток, собирающий урожай. Фьючерсы больше ориентированы на автоматический запуск потока (без уродливых и подверженных ошибкам накладных расходов) и на другие вещи, пока вам - исходному потоку - не понадобятся результаты.

23 голосов
/ 31 июля 2012

Future и Promise являются механизмами передачи результатов асинхронного вычисления от производителя к потребителю.

В случае Future вычисления определяется во время создания в будущем, и асинхронное выполнение начинается как можно скорее.Он также «знает», как создать асинхронные вычисления.

В случае Promise вычисления , его время начала и [возможно] асинхронный вызов отделен от механизма доставки.Когда вычисление результат доступен, Производитель должен явно вызвать deliver, что также означает, что Производитель контролирует , когда результат становится доступным.

Для Обещаний Clojure допускает ошибку проектирования, используя один и тот же объект (результат вызова promise), чтобы произвести (deliver) и использовать (deref) результат вычисление .Это две совершенно разные возможности и должны рассматриваться как таковые.

2 голосов
/ 10 апреля 2013

Уже есть отличные ответы, поэтому добавьте только сводку «как использовать»:

Оба

Создание обещания или будущего немедленно возвращает ссылкуЭта ссылка блокируется на @ / deref до тех пор, пока результат вычисления не будет предоставлен другим потоком.

Будущее

При создании будущего вы предоставляете синхронную работу для выполнения.Он выполняется в потоке из выделенного неограниченного пула.

Обещание

Вы не приводите аргументов при создании обещания.Ссылка должна быть передана другому «пользовательскому» потоку, который будет deliver результатом.

0 голосов
/ 07 января 2011

Во-первых, Promise - это Future.Я думаю, что вы хотите знать разницу между Promise и FutureTask.

A Future представляет значение, которое в настоящее время неизвестно, но будет известно в будущем.

A FutureTask представляет результат вычисления, которое произойдет в будущем (возможно, внекоторый пул потоков).Когда вы пытаетесь получить доступ к результату, если вычисление еще не произошло, оно блокируется.В противном случае результат возвращается немедленно.Никакая другая сторона не участвует в вычислении результата, так как вычисление указано вами заранее.

A Promise представляет результат, который будет обещан обещающим в будущем.В этом случае вы - обещанный, а обещающий - тот, кто дал вам объект Promise.Подобно FutureTask, если вы попытаетесь получить доступ к результату до того, как Promise будет выполнен, он будет заблокирован, пока обещающий не выполнит Promise.После выполнения Promise вы всегда и сразу получаете одно и то же значение.В отличие от FutureTask, здесь участвует другая сторона, которая сделала Promise.Эта другая сторона несет ответственность за выполнение вычислений и выполнение Promise.

В этом смысле FutureTask - это Promise, который вы сделали для себя.

...