Estoy leyendo SIP-14 y el concepto de Future
tiene mucho sentido y es fácil de entender. Pero tengo dos preguntas sobre Promise
:
El SIP dice
Depending on the implementation, it may be the case that p.future == p
. ¿Cómo puede ser esto? ¿SonFuture
yPromise
no dos tipos diferentes?¿Cuándo deberíamos usar un
Promise
? Elproducer and consumer
código de ejemplo :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() } }
es fácil de leer, pero ¿realmente necesitamos escribir así? Intenté implementarlo solo con Future y sin Promise como este:
val f = future {
produceSomething()
}
val producer = future {
continueDoingSomethingUnrelated()
}
startDoingSomething()
val consumer = future {
f onSuccess {
case r => doSomethingWithResult()
}
}
¿Cuál es la diferencia entre este y el ejemplo dado y qué hace necesaria una Promesa?
scala
concurrency
xiefei
fuente
fuente
Future
yPromise
son dos tipos separados, pero como puede ver en github.com/scala/scala/blob/master/src/library/scala/concurrent/… estaPromise
implementación particular también se extiendeFuture
.Respuestas:
La Promesa y el Futuro son conceptos complementarios. El futuro es un valor que se recuperará, bueno, en algún momento en el futuro y puedes hacer cosas con él cuando suceda ese evento. Por lo tanto, es el punto final de lectura o salida de un cálculo; es algo de lo que recupera un valor.
Una promesa es, por analogía, el lado de la escritura del cálculo. Creas una promesa que es el lugar donde colocarás el resultado del cálculo y de esa promesa obtienes un futuro que se utilizará para leer el resultado que se puso en la promesa. Cuando complete una Promesa, ya sea por fracaso o por éxito, activará todo el comportamiento que se adjuntó al Futuro asociado.
Respecto a tu primera pregunta, ¿cómo puede ser que por una promesa p tenemos
p.future == p
. Puede imaginar esto como un búfer de un solo elemento: un contenedor que inicialmente está vacío y puede almacenar un valor que se convertirá en su contenido para siempre. Ahora, dependiendo de su punto de vista, esto es tanto una promesa como un futuro. Es una promesa para alguien que tenga la intención de escribir el valor en el búfer. Es un futuro para alguien que espera que ese valor se ponga en el búfer.Específicamente, para la API concurrente de Scala, si echas un vistazo al rasgo Promise aquí , puedes ver cómo se implementan los métodos del objeto complementario Promise:
Ahora, las implementaciones de promesas, DefaultPromise y KeptPromise se pueden encontrar aquí . Ambos extienden un pequeño rasgo básico que tiene el mismo nombre, pero se encuentra en un paquete diferente:
Para que pueda ver lo que quieren decir
p.future == p
.DefaultPromise
es el búfer al que me refería anteriormente, mientras queKeptPromise
es un búfer con el valor puesto desde su creación.Con respecto a su ejemplo, el bloque futuro que usa allí en realidad crea una promesa detrás de escena. Echemos un vistazo a la definición de
future
de aquí :Siguiendo la cadena de métodos, terminas en el impl.Future :
Entonces, como puede ver, el resultado que obtiene de su bloque de productor se vierte en una promesa.
EDICIÓN POSTERIOR :
Con respecto al uso en el mundo real: la mayoría de las veces no se ocupará directamente de las promesas. Si va a utilizar una biblioteca que realiza cálculos asincrónicos, simplemente trabajará con los futuros devueltos por los métodos de la biblioteca. En este caso, las promesas son creadas por la biblioteca; solo está trabajando con el extremo de lectura de lo que hacen esos métodos.
Pero si necesita implementar su propia API asincrónica, tendrá que comenzar a trabajar con ellos. Suponga que necesita implementar un cliente HTTP asíncrono además de, digamos, Netty. Entonces su código se verá algo así
fuente
Promise
s debe estar en el código de implementación.Future
es algo agradable de solo lectura que puede exponer al código del cliente. Además, laFuture.future{...}
sintaxis a veces puede resultar complicada.def makeHTTPCall(request: Request): Future[Response] = { Future { registerOnCompleteCallback(buffer => { val response = makeResponse(buffer) response }) } }
registerOnCompleteCallback()
terminar. Además, no regresaFuture[Response]
. Vuelve en suFuture[registerOnCompleteCallback() return type]
lugar.