Qual é a diferença entre um futuro e uma promessa?

Qual é a diferença entre Future e Promise?
Ambos agem como um substituto para resultados futuros, mas onde está a principal diferença?

Author: Flip, 2013-01-26

9 answers

De acordo com esta discussão, Promise has finally been called CompletableFuture for inclusion in Java 8, and its javadoc explains:

Um Futuro que pode ser explicitamente completado (definindo o seu valor e estado), e pode ser usado como uma etapa de completação, suportando funções e acções dependentes que desencadeiam após a sua conclusão.

Também é dado um exemplo na lista:

f.then((s -> aStringFunction(s)).thenAsync(s -> ...);

Note que a API final é ligeiramente diferente mas permite execução assíncrona semelhante:

CompletableFuture<String> f = ...;
f.thenApply(this::modifyString).thenAccept(System.out::println);
 151
Author: assylias, 2015-06-03 08:51:39
(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 ... "podes fazer uma promessa e cabe-te a ti cumpri-la. Quando alguém faz uma promessa você deve esperar para ver se eles a honram no futuro"([5]}) resume muito bem, mas alguma explicação pode ser útil.

Futuros e promessas são conceitos muito semelhantes, a diferença é que um futuro é um recipiente apenas para 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 goiaba SettableFuture podem ser considerados como promessas, porque o seu valor pode ser definido ("concluído"), mas eles também implementam a interface futura, 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. Note Como a tarefa do futuro - um clássico future - must be initialized with a Callable or Runnable, there is no-argument constructor, and both Future and FutureTask are read-only from the outside (the set methods of FutureTask are protected). O valor será definido para 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 um) a qualquer hora porque tem um método de setter público. O futuro completo e o futuro estável podem ser criados sem qualquer tarefa, e seu valor pode ser definido a qualquer momento. Você envia uma promessa para o código do cliente, e cumpri-la mais tarde como desejar.

Note que o futuro completo não é uma promessa "pura", pode ser inicializado com uma tarefa tal como a futura tarefa, e a sua característica mais útil é o encadeamento não relacionado dos passos de processamento.

Note também que uma promessa não tem que ser um subtipo do futuro e não tem que ser o mesmo objeto. Em Scala um objeto futuro é criado por um assíncrono computação ou por um objeto de Promessa diferente . Em C++ a situação é semelhante: o objeto prometido é usado pelo produtor e o objeto futuro pelo consumidor. A vantagem desta separação é que o cliente não pode definir o valor do futuro.

Ambos a mola e a EJB 3.1 têm uma classe Assíncresulta, que é semelhante às promessas Scala/C++. AsyncResult do implement Future but this is not the real future: assynchronous methods in Spring / EJB return a objeto futuro diferente, apenas de leitura através de alguma magia de fundo, e este segundo futuro "real" pode ser usado pelo cliente para acessar o resultado.

 159
Author: lbalazscs, 2016-10-25 02:59:56

Estou ciente de que já há uma resposta aceite, mas gostaria de acrescentar a minha opinião:

TLDR: futuro e promessa são os dois lados de uma operação assíncrona: consumidor/ouvinte vs. produtor/executor.

Como um chamador de um método API assíncrono, você terá um Future como um manípulo para o resultado da computação. Você pode, por exemplo, chamar get() sobre ele para esperar que o cálculo para completar e recuperar o resultado.

Agora pense em como este método API é realmente implementado: o executor deve retornar um Future imediatamente. Eles são responsáveis por completar esse futuro assim que o cálculo é feito (que eles saberão porque ele está implementando a lógica de expedição ;-)). Eles vão usar um Promise/CompletableFuture para fazer exatamente isso: construir e retornar o CompletableFuture imediatamente, e chamar complete(T result) uma vez que a computação é feita.

 128
Author: Rahel Lüthy, 2019-02-13 08:14:30
Vou dar um exemplo do que é a promessa e como o seu valor pode ser definido a qualquer momento, em oposição ao futuro, que o valor só pode ser lido. Suponha que tem uma mãe e lhe pede dinheiro.
// Now , you trick your mom into creating you a promise of eventual
// donation, she gives you that promise object, but she is not really
// in rush to fulfill it yet:
Supplier<Integer> momsPurse = ()-> {

        try {
            Thread.sleep(1000);//mom is busy
        } catch (InterruptedException e) {
            ;
        }

        return 100;

    };


ExecutorService ex = Executors.newFixedThreadPool(10);

CompletableFuture<Integer> promise =  
CompletableFuture.supplyAsync(momsPurse, ex);

// You are happy, you run to thank you your mom:
promise.thenAccept(u->System.out.println("Thank you mom for $" + u ));

// But your father interferes and generally aborts mom's plans and 
// completes the promise (sets its value!) with far lesser contribution,
// as fathers do, very resolutely, while mom is slowly opening her purse 
// (remember the Thread.sleep(...)) :
promise.complete(10); 

A saída disto é:

Thank you mom for $10
A promessa da mãe foi criada, mas esperou por um evento de "conclusão".
CompletableFuture<Integer> promise...
Criaste tal evento, aceitaste a promessa dela e anunciaste os teus planos para agradecer à tua mãe.
promise.thenAccept...
Neste momento, a mãe começou a abri-la. bolsa...mas muito lento... E o pai interferiu muito mais depressa e cumpriu a promessa em vez da tua mãe.
promise.complete(10);
Reparaste num executor que escrevi explicitamente? Curiosamente, se você usar um executor implícito padrão em vez disso (commonPool) e o pai não está em casa, mas apenas a mãe com sua "bolsa lenta", então sua promessa só vai completar, se o programa viver mais tempo do que a mãe precisa para obter dinheiro da Bolsa.

O executor por omissão age como um "daemon" e não espera que todas as promessas sejam cumpridas. Não encontrei uma boa descrição deste facto...

 97
Author: Vladimir Nabokov, 2019-11-05 11:34:52

Não tenho a certeza se isto pode ser uma resposta, mas como vejo o que os outros disseram para alguém, pode parecer que você precisa de duas abstrações separadas para ambos os conceitos, de modo que um deles (Future) é apenas uma visão apenas de leitura do outro (Promise) ... mas, na verdade, isso não é necessário.

Por exemplo, dê uma olhada em 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 compostabilidade usando o método then como:

asyncOp1()
.then(function(op1Result){
  // do something
  return asyncOp2();
})
.then(function(op2Result){
  // do something more
  return asyncOp3();
})
.then(function(op3Result){
  // do something even more
  return syncOp4(op3Result);
})
...
.then(function(result){
  console.log(result);
})
.catch(function(error){
  console.log(error);
})

O que faz com que a computação assíncrona pareça síncrona:

try {
  op1Result = syncOp1();
  // do something
  op1Result = syncOp2();
  // do something more
  op3Result = syncOp3();
  // do something even more
  syncOp4(op3Result);
  ...
  console.log(result);
} catch(error) {
  console.log(error);
}
O que é muito fixe. (Não tão legal quanto async-await mas async-await {[[28]} apenas remove o boilerplate ....then (function (result) {....[[28]} a partir dele). E, na verdade, a sua abstração é muito boa como a construtora de promessas.
new Promise( function(resolve, reject) { /* do it */ } );

Permite-lhe fornecer dois callbacks que podem ser usados para completar o Promise com sucesso ou com um erro. De modo que apenas o código que constrói o Promise pode completá-lo e o código que recebe um objeto Promise já construído tem a vista apenas para leitura.

Com herança o acima pode ser alcançado se resolver e rejeitar são métodos protegidos.

 10
Author: bodrin, 2016-05-27 07:37:52

Para o código do cliente, a promessa é para observar ou anexar callback quando um resultado está disponível, enquanto o futuro é esperar pelo resultado e, em seguida, continuar. Teoricamente tudo o que é possível fazer com futuros o que pode ser feito com promessas, mas devido à diferença de estilo, a API resultante para promessas em diferentes idiomas torna mais fácil acordes.

 5
Author: user2562234, 2017-11-25 18:10:38

Nenhum método set na interface futura, apenas o método get, por isso é apenas para leitura. Sobre o futuro completo, este artigo pode ser útil. Completo

 2
Author: Jacky, 2017-09-06 17:33:43

In this example you can take a look at how Promises can be used in Java para criar sequências assíncronas de chamadas:

doSomeProcess()
    .whenResult(result -> System.out.println(String.format("Result of some process is '%s'", result)))
    .whenException(e -> System.out.println(String.format("Exception after some process is '%s'", e.getMessage())))
    .map(String::toLowerCase)
    .mapEx((result, e) -> e == null ? String.format("The mapped result is '%s'", result) : e.getMessage())
    .whenResult(s -> System.out.println(s));
 0
Author: George Meyer, 2020-07-02 12:51:37

Future e Promise são objectos proxy para resultado desconhecido

Promise completa a Future

  • Future - leitura / consumo de resultado desconhecido

  • Promise - write / producer of unknown result.

//Future has a reference to Promise
Future -> Promise

Como um producer Eu promise algo e responsável por isso

Como um consumer que recuperou um promise espero ter um resultado em future

Quanto a Java CompletableFutures é um {[[2]} porque você pode definir o resultado e também ele instrumentos Future

 0
Author: yoAlex5, 2021-02-06 21:58:53