Ich lese SIP-14 und das Konzept von Future
macht vollkommen Sinn und ist leicht zu verstehen. Habe aber zwei Fragen zu Promise
:
Das SIP sagt
Depending on the implementation, it may be the case that p.future == p
. Wie kann das sein? SindFuture
undPromise
nicht zwei verschiedene Typen?Wann sollten wir ein verwenden
Promise
? Der Beispielcodeproducer and consumer
:import scala.concurrent.{ future, promise } val p = promise[T] val f = p.future val producer = future { val r = produceSomething() p success r continueDoingSomethingUnrelated() } val consumer = future { startDoingSomething() f onSuccess { case r => doSomethingWithResult() } }
ist leicht zu lesen, aber müssen wir wirklich so schreiben? Ich habe versucht, es nur mit Future und ohne Promise wie folgt umzusetzen:
val f = future {
produceSomething()
}
val producer = future {
continueDoingSomethingUnrelated()
}
startDoingSomething()
val consumer = future {
f onSuccess {
case r => doSomethingWithResult()
}
}
Was ist der Unterschied zwischen diesem und dem gegebenen Beispiel und was macht ein Versprechen notwendig?
scala
concurrency
xiefei
quelle
quelle
Future
und esPromise
gibt zwei verschiedene Typen, aber wie Sie unter github.com/scala/scala/blob/master/src/library/scala/concurrent/… sehen könnenPromise
, erstreckt sich diese spezielle ImplementierungFuture
auch.Antworten:
Das Versprechen und die Zukunft sind komplementäre Konzepte. Die Zukunft ist ein Wert, der irgendwann in der Zukunft abgerufen wird, und Sie können damit etwas anfangen, wenn dieses Ereignis eintritt. Es ist daher der ausgelesene oder ausgelesene Endpunkt einer Berechnung - es ist etwas, von dem Sie einen Wert abrufen.
Ein Versprechen ist analog die Schreibseite der Berechnung. Sie erstellen ein Versprechen, an dem Sie das Ergebnis der Berechnung ablegen, und aus diesem Versprechen erhalten Sie eine Zukunft, in der Sie das Ergebnis lesen können, das in das Versprechen aufgenommen wurde. Wenn Sie ein Versprechen entweder durch Misserfolg oder Erfolg erfüllen, lösen Sie das gesamte Verhalten aus, das mit der zugehörigen Zukunft verbunden war.
In Bezug auf Ihre erste Frage, wie kann es sein, dass wir ein Versprechen haben
p.future == p
? Sie können sich dies wie einen Einzelelementpuffer vorstellen - einen Container, der anfangs leer ist, und Sie können Nachwörter einen Wert speichern, der für immer zum Inhalt wird. Abhängig von Ihrer Sichtweise ist dies nun sowohl ein Versprechen als auch eine Zukunft. Es ist ein Versprechen für jemanden, der beabsichtigt, den Wert in den Puffer zu schreiben. Es ist eine Zukunft für jemanden, der darauf wartet, dass dieser Wert in den Puffer gestellt wird.Insbesondere für die gleichzeitige Scala-API können Sie anhand der Promise-Eigenschaft hier sehen, wie die Methoden aus dem Promise-Begleitobjekt implementiert werden:
Die Umsetzung der Versprechen DefaultPromise und KeptPromise finden Sie hier . Beide erweitern ein kleines Basismerkmal, das zufällig denselben Namen hat, sich jedoch in einem anderen Paket befindet:
So können Sie sehen, was sie bedeuten
p.future == p
.DefaultPromise
ist der Puffer, auf den ich mich oben bezogen habe, währendKeptPromise
es sich um einen Puffer handelt, dessen Wert von Anfang an eingegeben wurde.In Bezug auf Ihr Beispiel schafft der zukünftige Block, den Sie dort verwenden, tatsächlich ein Versprechen hinter den Kulissen. Schauen wir uns die Definition der
future
in hier :Wenn Sie der Methodenkette folgen, gelangen Sie in die impl.Future :
Wie Sie sehen, wird das Ergebnis, das Sie von Ihrem Produzentenblock erhalten, in ein Versprechen umgewandelt.
SPÄTER BEARBEITEN :
In Bezug auf die reale Verwendung: Meistens werden Sie nicht direkt mit Versprechungen umgehen. Wenn Sie eine Bibliothek verwenden, die asynchrone Berechnungen durchführt, arbeiten Sie nur mit den von den Methoden der Bibliothek zurückgegebenen Futures. Versprechen werden in diesem Fall von der Bibliothek erstellt - Sie arbeiten nur mit dem Leseende dieser Methoden.
Wenn Sie jedoch Ihre eigene asynchrone API implementieren müssen, müssen Sie mit ihnen arbeiten. Angenommen, Sie müssen einen asynchronen HTTP-Client zusätzlich zu Netty implementieren. Dann sieht Ihr Code ungefähr so aus
quelle
Promise
s sollte im Implementierungscode enthalten sein.Future
ist eine nette, schreibgeschützte Sache, die Sie dem Client-Code aussetzen können. Außerdem kann dieFuture.future{...}
Syntax manchmal umständlich sein.def makeHTTPCall(request: Request): Future[Response] = { Future { registerOnCompleteCallback(buffer => { val response = makeResponse(buffer) response }) } }
registerOnCompleteCallback()
Abschluss abgeschlossen ist. Auch dann , wenn es nicht zurückFuture[Response]
. Es kehrtFuture[registerOnCompleteCallback() return type]
stattdessen zurück.