ChatGPT解决这个技术问题 Extra ChatGPT

What's the difference between a Future and a Promise?

What's the difference between Future and Promise?
They both act like a placeholder for future results, but where is the main difference?

You can make a Promise and it's up to you to keep it. When someone else makes you a promise you must wait to see if they honour it in the Future
One of the least helpful Wikipedia articles I've ever read

h
hc_dev

(I'm not completely happy with the answers so far, so here is my attempt...)

I think that Kevin Wright's comment

You can make a Promise and it's up to you to keep it. When someone else makes you a promise you must wait to see if they honour it in the Future

summarizes it pretty well, but some explanation can be useful.

Futures and promises are pretty similar concepts, the difference is that a future is a read-only container for a result that does not yet exist, while a promise can be written (normally only once). The Java 8 CompletableFuture and the Guava SettableFuture can be thought of as promises, because their value can be set ("completed"), but they also implement the Future interface, therefore there is no difference for the client.

The result of the future will be set by "someone else" - by the result of an asynchronous computation. Note how FutureTask - a classic future - must be initialized with a Callable or Runnable, there is no no-argument constructor, and both Future and FutureTask are read-only from the outside (the set methods of FutureTask are protected). The value will be set to the result of the computation from the inside.

On the other hand, the result of a promise can be set by "you" (or in fact by anybody) anytime because it has a public setter method. Both CompletableFuture and SettableFuture can be created without any task, and their value can be set at any time. You send a promise to the client code, and fulfill it later as you wish.

Note that CompletableFuture is not a "pure" promise, it can be initialized with a task just like FutureTask, and its most useful feature is the unrelated chaining of processing steps.

Also note that a promise does not have to be a subtype of future and it does not have to be the same object. In Scala a Future object is created by an asynchronous computation or by a different Promise object. In C++ the situation is similar: the promise object is used by the producer and the future object by the consumer. The advantage of this separation is that the client cannot set the value of the future.

Both Spring and EJB 3.1 have an AsyncResult class, which is similar to the Scala/C++ promises. AsyncResult does implement Future but this is not the real future: asynchronous methods in Spring/EJB return a different, read-only Future object through some background magic, and this second "real" future can be used by the client to access the result.


I try to remember the difference as two ends of a pipe or a dead letter box. Promise allows to provide data, Future allows to retrieve it. That a Promise is often a Future too is convenience, I guess.
a
assylias

According to this discussion, Promise has finally been called CompletableFuture for inclusion in Java 8, and its javadoc explains:

A Future that may be explicitly completed (setting its value and status), and may be used as a CompletionStage, supporting dependent functions and actions that trigger upon its completion.

An example is also given on the list:

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

Note that the final API is slightly different but allows similar asynchronous execution:

CompletableFuture<String> f = ...;
f.thenApply(this::modifyString).thenAccept(System.out::println);

It's not your fault Assylias, but that javadoc extract needs a serious workover by a decent tech author. On my fifth read-through I can just start to appreciate what it's trying to say ... and I come to this with an understanding of futures and promises already in place!
@Beetroot-Beetroot it seems that has happened by now.
@herman Thanks - I've updated the link to point to the final version of the javadoc.
@Beetroot-Beetroot You should check out the doc for the Exceptionally method. It would make a wonderful poem, but is an exceptional failure of readable documentation.
For anyone wondering, @Fulluphigh is referring to this. Looks like it was removed/overhauled in Java 8.
R
Rahel Lüthy

I am aware that there's already an accepted answer but would like to add my two cents nevertheless:

TLDR: Future and Promise are the two sides of an asynchronous operation: consumer/caller vs. producer/implementor.

As a caller of an asynchronous API method, you will get a Future as a handle to the computation's result. You can e.g. call get() on it to wait for the computation to complete and retrieve the result.

Now think of how this API method is actually implemented: The implementor must return a Future immediately. They are responsible for completing that future as soon as the computation is done (which they will know because it is implementing the dispatch logic ;-)). They will use a Promise/CompletableFuture to do just that: Construct and return the CompletableFuture immediately, and call complete(T result) once the computation is done.


Does this imply that a Promise is always a subclass of Future, and that the writeability of the Future is just obscured by the type?
I don't think that it is implied. Implementation-wise, it will often be the case though (e.g. in Java, Scala).
Y
Yolgie

I will give an example of what is Promise and how its value could be set at any time, in opposite to Future, which value is only readable.

Suppose you have a mom and you ask her for money.

// 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); 

Output of that is:

Thank you mom for $10

Mom's promise was created , but waited for some "completion" event.

CompletableFuture<Integer> promise...

You created such event, accepting her promise and announcing your plans to thank your mom:

promise.thenAccept...

At this moment mom started open her purse...but very slow...

and father interfered much faster and completed the promise instead of your mom:

promise.complete(10);

Have you noticed an executor that I wrote explicitly?

Interestingly, if you use a default implicit executor instead (commonPool) and father is not at home, but only mom with her "slow purse", then her promise will only complete, if the program lives longer than mom needs to get money from the purse.

The default executor acts kind of like a "daemon" and does not wait for all promises to be fulfilled. I have not found a good description of this fact...


It's so much fun to read this one! I don't think I could forget future and promise anymore.
This must be accepted as the answer. Its just like reading a story. Thanks @Vladimir
Thanks @Vladimir
High-level programming languages just have coined new terms for existing concepts, I come from a low-level background and have been using promise and future for years without actually knowing they are called so.
Said Mom does not check Promise status, and continues to eat RAM and CPU; How can we check status and abort?
b
bodrin

Not sure if this can be an answer but as I see what others have said for someone it may look like you need two separate abstractions for both of these concepts so that one of them (Future) is just a read-only view of the other (Promise) ... but actually this is not needed.

For example take a look at how promises are defined in javascript:

https://promisesaplus.com/

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

The focus is on the composability using the then method like:

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);
})

which makes asynchronous computation to look like synchronous:

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);
}

which is pretty cool. (Not as cool as async-await but async-await just removes the boilerplate ....then(function(result) {.... from it).

And actually their abstraction is pretty good as the promise constructor

new Promise( function(resolve, reject) { /* do it */ } );

allows you to provide two callbacks which can be used to either complete the Promise successfully or with an error. So that only the code that constructs the Promise can complete it and the code that receives an already constructed Promise object has the read-only view.

With inheritance the above can be achieved if resolve and reject are protected methods.


+1. This is the correct answer to this question. CompletableFuture might have some similarity to a Promise but it still isn't a Promise, because the way it's intended to be consumed is different: a Promise's result is consumed by calling then(function), and the function is executed in the context of the producer immediately after the producer calls resolve. A Future's result is consumed by calling get which causes the consumer thread to wait until the producer thread has generated the value, then processes it in the consumer. Future is inherently multithreaded, but...
...it is entirely possible to use a Promise with only a single thread (and in fact that is the precise environment they were originally designed for: javascript applications generally only have a single thread, so you cannot implement Future there). Promise is therefore much more lightweight and efficient than Future, but Future can be helpful in situations that are more complex and require cooperation between threads that can't easily be arranged by using Promises. To summarize: Promise is a push model, while Future is a pull model (cf Iterable vs Observable)
@PeriataBreatta Even in a single-threaded environment, there must be something fulfilling the promise (which typically sort of runs as a different thread, e.g., an XMLHttpRequest). I don't believe the efficiency claim, do you happen to have some figures? +++ That said, a very nice explanation.
@maaartinus - yes, something must fulfil the promise, but it can (and in fact in many cases is) done by using a top level loop that polls for changes in external state and resolves whichever promises relate to actions that have finished. Efficiency wise, I have no firm figures for Promises specifically, but note that calling get on an unresolved Future will necessarily involve 2 thread context switches, which at least a few years back was likely to require around 50 us.
@PeriataBreatta Actually your comment should be the accepted solution. I was looking for an explanation (pull/push, single/multi-thread) like yours.
u
user2562234

For client code, Promise is for observing or attaching callback when a result is available, whereas Future is to wait for result and then continue. Theoretically anything which is possible to do with futures what can done with promises, but due to the style difference, the resultant API for promises in different languages make chaining easier.


J
Jacky

No set method in Future interface, only get method, so it is read-only. About CompletableFuture, this article maybe helpful. completablefuture


y
yoAlex5

Future and Promise are proxy object for unknown result

Promise completes a Future

Promise - write/producer of unknown result.

Future - read/consumer of unknown result. It has next states: pending, fulfilled, canceled

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

As a producer I promise something and responsible for it

As a consumer who retrieved a promise I expect to have a result in future. In future I can use the promise or reject it

As for Java CompletableFutures it is a Promise because you can set the result and also it implements Future


G
George Meyer

In this example you can take a look at how Promises can be used in Java for creating asynchronous sequences of calls:

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));