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

186,529

Solution 1

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

Solution 2

(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.

Solution 3

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.

Solution 4

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...

Solution 5

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.

Share:
186,529
Evgenij Reznik
Author by

Evgenij Reznik

Updated on July 08, 2022

Comments

  • Evgenij Reznik
    Evgenij Reznik almost 2 years

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

  • Beetroot-Beetroot
    Beetroot-Beetroot about 11 years
    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!
  • herman
    herman almost 9 years
    @Beetroot-Beetroot it seems that has happened by now.
  • assylias
    assylias almost 9 years
    @herman Thanks - I've updated the link to point to the final version of the javadoc.
  • Fulluphigh
    Fulluphigh over 8 years
    @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.
  • JayArby
    JayArby almost 8 years
    @Fulluphigh That documentation is actually hilarious.
  • Periata Breatta
    Periata Breatta over 7 years
    +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...
  • Periata Breatta
    Periata Breatta over 7 years
    ...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)
  • maaartinus
    maaartinus over 7 years
    @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.
  • Periata Breatta
    Periata Breatta over 7 years
    @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.
  • Cedric Reichenbach
    Cedric Reichenbach over 7 years
    For anyone wondering, @Fulluphigh is referring to this. Looks like it was removed/overhauled in Java 8.
  • user1532146
    user1532146 over 6 years
    It's so much fun to read this one! I don't think I could forget future and promise anymore.
  • devios1
    devios1 about 6 years
    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?
  • Rahel Lüthy
    Rahel Lüthy about 6 years
    I don't think that it is implied. Implementation-wise, it will often be the case though (e.g. in Java, Scala).
  • Phillen
    Phillen about 5 years
    This must be accepted as the answer. Its just like reading a story. Thanks @Vladimir
  • Thomas Jacob
    Thomas Jacob almost 5 years
    @PeriataBreatta Actually your comment should be the accepted solution. I was looking for an explanation (pull/push, single/multi-thread) like yours.
  • intvprep
    intvprep about 4 years
    Thanks @Vladimir
  • Sniper
    Sniper almost 4 years
    @CedricReichenbach link seems to be broken
  • Cedric Reichenbach
    Cedric Reichenbach almost 4 years
  • Harald
    Harald over 3 years
    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.
  • Abhishek Sagar
    Abhishek Sagar over 2 years
    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.
  • Carmine Ingaldi
    Carmine Ingaldi over 2 years
    <<Not as cool as async-await but async-await just removes the boilerplate>> this construct is not just syntactic sugar: async/await makes promises work like future, as it blocks the computation until the promise is fulfilled/rejected. with .then() you can still execute the remaining code in your function immediately, with async/await, all the subsequent instructions will be delayed
  • Top-Master
    Top-Master about 2 years
    Said Mom does not check Promise status, and continues to eat RAM and CPU; How can we check status and abort?