Estou lendo SIP-14 e o conceito de Future
faz todo o sentido e fácil de entender. Mas tenho duas perguntas sobre Promise
:
O SIP diz
Depending on the implementation, it may be the case that p.future == p
. Como isso pode ser? SãoFuture
ePromise
não dois tipos diferentes?Quando devemos usar um
Promise
? Oproducer and consumer
código de exemplo :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() } }
é fácil de ler, mas realmente precisamos escrever assim? Tentei implementá-lo apenas com Future and without Promise assim:
val f = future {
produceSomething()
}
val producer = future {
continueDoingSomethingUnrelated()
}
startDoingSomething()
val consumer = future {
f onSuccess {
case r => doSomethingWithResult()
}
}
Qual é a diferença entre este e o exemplo dado e o que torna uma promessa necessária?
scala
concurrency
xiefei
fonte
fonte
Future
ePromise
são dois tipos separados, mas como você pode ver em github.com/scala/scala/blob/master/src/library/scala/concurrent/… estaPromise
implementação específica também se estendeFuture
.Respostas:
A promessa e o futuro são conceitos complementares. O Futuro é um valor que será recuperado, bem, em algum momento no futuro e você pode fazer coisas com ele quando esse evento acontecer. É, portanto, o ponto final de leitura ou saída de um cálculo - é algo de onde você recupera um valor.
Uma promessa é, por analogia, o lado da escrita do cálculo. Você cria uma promessa que é o lugar onde você colocará o resultado do cálculo e dessa promessa você obterá um futuro que será usado para ler o resultado que foi colocado na promessa. Ao cumprir uma promessa, seja por fracasso ou sucesso, você acionará todo o comportamento que estava vinculado ao futuro associado.
Com relação à sua primeira pergunta, como pode ser isso para uma promessa p que temos
p.future == p
. Você pode imaginar isso como um buffer de item único - um contêiner que está inicialmente vazio e você pode armazenar um valor que se tornará seu conteúdo para sempre. Agora, dependendo do seu ponto de vista, isso é uma promessa e um futuro. É uma promessa para quem pretende escrever o valor no buffer. É um futuro para quem espera que esse valor seja colocado no buffer.Especificamente, para a API simultânea Scala, se você der uma olhada no traço Promise aqui, poderá ver como os métodos do objeto complementar Promise são implementados:
Agora, essas implementações de promessas, DefaultPromise e KeptPromise podem ser encontradas aqui . Ambos estendem um pequeno traço básico que por acaso tem o mesmo nome, mas está localizado em um pacote diferente:
Então você pode ver o que eles querem dizer
p.future == p
.DefaultPromise
é o buffer que estava me referindo acima, enquantoKeptPromise
é um buffer com o valor colocado desde sua criação.Em relação ao seu exemplo, o bloco futuro que você usa ali cria uma promessa nos bastidores. Vamos olhar a definição de
future
em aqui :Seguindo a cadeia de métodos, você acaba no impl.Future :
Então, como você pode ver, o resultado que você obtém do seu bloco produtor é transformado em uma promessa.
EDIÇÃO DEPOIS :
Com relação ao uso no mundo real: na maioria das vezes, você não lida diretamente com as promessas. Se você usar uma biblioteca que realiza computação assíncrona, trabalhará apenas com o futuro retornado pelos métodos da biblioteca. As promessas são, neste caso, criadas pela biblioteca - você está apenas trabalhando com a leitura do que esses métodos fazem.
Mas se você precisar implementar sua própria API assíncrona, terá que começar a trabalhar com eles. Suponha que você precise implementar um cliente HTTP assíncrono em cima de, digamos, Netty. Então, seu código será parecido com este
fonte
Promise
s deve estar no código de implementação.Future
é uma coisa boa, somente leitura, que você pode expor ao código do cliente. Além disso, aFuture.future{...}
sintaxe às vezes pode ser complicada.def makeHTTPCall(request: Request): Future[Response] = { Future { registerOnCompleteCallback(buffer => { val response = makeResponse(buffer) response }) } }
registerOnCompleteCallback()
terminar. Além disso, ele não retornaFuture[Response]
. EmFuture[registerOnCompleteCallback() return type]
vez disso, ele retorna .