Qual é a diferença entre Future
e Promise
?
Ambos agem como um espaço reservado para resultados futuros, mas qual é a principal diferença?
java
concurrency
future
promise
user1170330
fonte
fonte
Promise
e depende de você mantê-lo. Quando alguém lhe faz uma promessa que você deve esperar para ver se eles honrá-lo noFuture
Respostas:
De acordo com essa discussão ,
Promise
finalmente foi chamadoCompletableFuture
para inclusão no Java 8 e seu javadoc explica:Um exemplo também é dado na lista:
Observe que a API final é um pouco diferente, mas permite execução assíncrona semelhante:
fonte
(Eu não estou completamente feliz com as respostas até agora, então aqui está minha tentativa ...)
Acho que o comentário de Kevin Wright ( "Você pode fazer uma promessa e depende de você cumpri-la. Quando alguém lhe faz uma promessa, você deve esperar para ver se a honrará no futuro" ) resume muito bem, mas alguns explicação pode ser útil.
Futuros e promessas são conceitos bastante semelhantes, a diferença é que o futuro é um contêiner somente leitura para um resultado que ainda não existe, enquanto uma promessa pode ser escrita (normalmente apenas uma vez). O Java 8 CompletableFuture e o Guava SettableFuture podem ser considerados promissores, porque seu valor pode ser definido ("concluído"), mas eles também implementam a interface Future, portanto, não há diferença para o cliente.
O resultado do futuro será definido por "outra pessoa" - pelo resultado de uma computação assíncrona. Observe como o FutureTask - um futuro clássico - deve ser inicializado com um Callable ou Runnable, não há construtor sem argumentos e o Future e o FutureTask são somente leitura de fora (os métodos definidos do FutureTask estão protegidos). O valor será definido como o resultado da computação a partir do interior.
Por outro lado, o resultado de uma promessa pode ser definido por "você" (ou, de fato, por qualquer pessoa) a qualquer momento, porque possui um método público de configuração. CompletableFuture e SettableFuture podem ser criados sem qualquer tarefa e seu valor pode ser definido a qualquer momento. Você envia uma promessa ao código do cliente e a cumpre mais tarde, conforme desejar.
Observe que CompletableFuture não é uma promessa "pura", pode ser inicializada com uma tarefa como a FutureTask, e seu recurso mais útil é o encadeamento não relacionado das etapas de processamento.
Observe também que uma promessa não precisa ser um subtipo de futuro e não precisa ser o mesmo objeto. No Scala, um objeto Futuro é criado por uma computação assíncrona ou por um objeto Promise diferente . Em C ++, a situação é semelhante: o objeto de promessa é usado pelo produtor e o objeto futuro pelo consumidor. A vantagem dessa separação é que o cliente não pode definir o valor do futuro.
O Spring e o EJB 3.1 têm uma classe AsyncResult, que é semelhante às promessas do Scala / C ++. O AsyncResult implementa Future, mas este não é o futuro real: métodos assíncronos no Spring / EJB retornam um objeto Future diferente, somente leitura, através de alguma mágica de fundo, e esse segundo futuro "real" pode ser usado pelo cliente para acessar o resultado.
fonte
Estou ciente de que já existe uma resposta aceita, mas gostaria de acrescentar meus dois centavos:
TLDR: Futuro e Promessa são os dois lados de uma operação assíncrona: consumidor / chamador vs. produtor / implementador .
Como chamador de um método de API assíncrono, você receberá
Future
um identificador para o resultado da computação. Você pode, por exemplo, solicitarget()
que o cálculo seja concluído e recuperar o resultado.Agora pense em como esse método de API é realmente implementado: O implementador deve retornar um
Future
imediatamente. Eles são responsáveis por concluir esse futuro assim que o cálculo for concluído (o que eles saberão porque está implementando a lógica de despacho ;-)). Eles usarão umPromise
/CompletableFuture
para fazer exatamente isso: Construa e retorne oCompletableFuture
imediatamente, e chamecomplete(T result)
assim que o cálculo estiver concluído.fonte
Vou dar um exemplo do que é Promise e como seu valor pode ser definido a qualquer momento, ao contrário de Future, cujo valor é apenas legível.
Suponha que você tenha uma mãe e peça dinheiro a ela.
Saída disso é:
A promessa da mamãe foi criada, mas esperou por algum evento de "conclusão".
Você criou esse evento, aceitando a promessa dela e anunciando seus planos de agradecer à sua mãe:
Nesse momento a mãe começou a abrir a bolsa ... mas muito devagar ...
e pai interferiram muito mais rápido e cumpriram a promessa em vez de sua mãe:
Você notou um executor que eu escrevi explicitamente?
Curiosamente, se você usar um executor implícito padrão (commonPool) e o pai não estiver em casa, mas apenas a mãe com sua "bolsa lenta", sua promessa só será concluída se o programa viver mais do que a mãe precisa obter dinheiro com o Bolsa.
O executor padrão age como um "daemon" e não espera que todas as promessas sejam cumpridas. Não encontrei uma boa descrição desse fato ...
fonte
Não tenho certeza se isso pode ser uma resposta, mas como vejo o que os outros disseram para alguém, pode parecer que você precise de duas abstrações separadas para esses dois conceitos, de modo que um deles (
Future
) seja apenas uma visualização somente leitura do outro (Promise
) ... mas, na verdade, isso não é necessário.Por exemplo, veja como as promessas são definidas em javascript:
https://promisesaplus.com/
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
O foco está na composibilidade usando o
then
método como:que faz com que a computação assíncrona pareça síncrona:
o que é bem legal. (Não é tão legal quanto o assíncrono-aguardar, mas o assíncrono-aguarda apenas remove o clichê ... então (function (result) {.... dele).
E, na verdade, sua abstração é muito boa como construtora de promessas
permite fornecer dois retornos de chamada que podem ser usados para concluir com
Promise
êxito ou com um erro. Para que apenas o código que constrói oPromise
possa concluí-lo e o código que recebe umPromise
objeto já construído tenha a exibição somente leitura.Com a herança, o acima pode ser alcançado se resolver e rejeitar forem métodos protegidos.
fonte
CompletableFuture
pode ter alguma semelhança com a,Promise
mas ainda não éPromise
, porque a maneira como se destina a ser consumida é diferente:Promise
o resultado de a é consumido pela chamadathen(function)
e a função é executada no contexto do produtor imediatamente após a ligação do produtor.resolve
. OFuture
resultado de A é consumido pela chamada,get
que faz com que o encadeamento do consumidor aguarde até que o encadeamento do produtor gere o valor e o processe no consumidor.Future
é inerentemente multithreaded, mas ...Promise
com apenas um thread (e, de fato, esse é o ambiente preciso para o qual foram projetados originalmente: aplicativos javascript geralmente têm apenas um thread, portanto você não pode implementáFuture
-lo).Promise
é, portanto, muito mais leve e eficiente do queFuture
, masFuture
pode ser útil em situações mais complexas e que exijam cooperação entre encadeamentos que não podem ser facilmente organizados usandoPromise
s. Para resumir:Promise
é um modelo de impulso, enquanto queFuture
é um modelo de recepção (cf Iterable vs observável)XMLHttpRequest
). Eu não acredito na alegação de eficiência, você tem alguns números? +++ Dito isto, uma explicação muito boa.get
de uma soluçãoFuture
não resolvida envolverá necessariamente duas alternâncias de contexto de encadeamento, que pelo menos alguns anos atrás provavelmente exigiriam cerca de 50 nós .Para o código do cliente, o Promise é para observar ou anexar retorno de chamada quando um resultado estiver disponível, enquanto Futuro é aguardar pelo resultado e continuar. Teoricamente, tudo o que é possível fazer com os futuros pode ser feito com promessas, mas devido à diferença de estilo, a API resultante de promessas em diferentes idiomas facilita o encadeamento.
fonte
Nenhum método definido na interface Futuro, apenas o método get, portanto, é somente leitura. Sobre o CompletableFuture, este artigo pode ser útil. completablefuture
fonte